diff --git a/assets/character/BlackSwan.png b/assets/character/BlackSwan.png new file mode 100644 index 000000000..05778533c Binary files /dev/null and b/assets/character/BlackSwan.png differ diff --git a/assets/character/DrRatio.png b/assets/character/DrRatio.png new file mode 100644 index 000000000..1383b38a6 Binary files /dev/null and b/assets/character/DrRatio.png differ diff --git a/assets/character/Misha.png b/assets/character/Misha.png new file mode 100644 index 000000000..d12010ad1 Binary files /dev/null and b/assets/character/Misha.png differ diff --git a/assets/character/Sparkle.png b/assets/character/Sparkle.png new file mode 100644 index 000000000..fc5b3e4c5 Binary files /dev/null and b/assets/character/Sparkle.png differ diff --git a/assets/share/base/page/MAIN_GOTO_CHARACTER.2.png b/assets/share/base/page/MAIN_GOTO_CHARACTER.2.png new file mode 100644 index 000000000..ebf008360 Binary files /dev/null and b/assets/share/base/page/MAIN_GOTO_CHARACTER.2.png differ diff --git a/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.SEARCH.png b/assets/share/character/switch/Huohuo.png similarity index 74% rename from assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.SEARCH.png rename to assets/share/character/switch/Huohuo.png index 818234f75..75757d1da 100644 Binary files a/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.SEARCH.png and b/assets/share/character/switch/Huohuo.png differ diff --git a/assets/share/combat/interact/DUNGEON_COMBAT_INTERACT.2.png b/assets/share/combat/interact/DUNGEON_COMBAT_INTERACT.2.png new file mode 100644 index 000000000..5e96aa5d2 Binary files /dev/null and b/assets/share/combat/interact/DUNGEON_COMBAT_INTERACT.2.png differ diff --git a/assets/share/combat/interact/MAP_LOADING.SEARCH.png b/assets/share/combat/interact/MAP_LOADING.SEARCH.png index 9a1c84aa5..ffccbd6d1 100644 Binary files a/assets/share/combat/interact/MAP_LOADING.SEARCH.png and b/assets/share/combat/interact/MAP_LOADING.SEARCH.png differ diff --git a/assets/share/combat/state/COMBAT_AUTO.BUTTON.png b/assets/share/combat/state/COMBAT_AUTO.BUTTON.png new file mode 100644 index 000000000..b736577b7 Binary files /dev/null and b/assets/share/combat/state/COMBAT_AUTO.BUTTON.png differ diff --git a/assets/share/combat/state/COMBAT_SPEED_2X.BUTTON.png b/assets/share/combat/state/COMBAT_SPEED_2X.BUTTON.png new file mode 100644 index 000000000..158f621a0 Binary files /dev/null and b/assets/share/combat/state/COMBAT_SPEED_2X.BUTTON.png differ diff --git a/assets/share/combat/support/COMBAT_SUPPORT_ADD.png b/assets/share/combat/support/COMBAT_SUPPORT_ADD.png index 586c9e0e5..48f0e0e63 100644 Binary files a/assets/share/combat/support/COMBAT_SUPPORT_ADD.png and b/assets/share/combat/support/COMBAT_SUPPORT_ADD.png differ diff --git a/assets/share/combat/support/COMBAT_SUPPORT_LIST.png b/assets/share/combat/support/COMBAT_SUPPORT_LIST.png index d22e1c0d1..9917bea76 100644 Binary files a/assets/share/combat/support/COMBAT_SUPPORT_LIST.png and b/assets/share/combat/support/COMBAT_SUPPORT_LIST.png differ diff --git a/assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png b/assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png index 3029cfbb8..a9839d371 100644 Binary files a/assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png and b/assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png differ diff --git a/assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png b/assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png index aea5bb872..1e4779af3 100644 Binary files a/assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png and b/assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png differ diff --git a/assets/share/combat/support/SUPPORT_SELECTED.2.png b/assets/share/combat/support/SUPPORT_SELECTED.2.png new file mode 100644 index 000000000..1b74ed76d Binary files /dev/null and b/assets/share/combat/support/SUPPORT_SELECTED.2.png differ diff --git a/assets/share/combat/support/SUPPORT_SELECTED.3.png b/assets/share/combat/support/SUPPORT_SELECTED.3.png new file mode 100644 index 000000000..716dedc85 Binary files /dev/null and b/assets/share/combat/support/SUPPORT_SELECTED.3.png differ diff --git a/assets/share/combat/support/SUPPORT_SELECTED.4.png b/assets/share/combat/support/SUPPORT_SELECTED.4.png new file mode 100644 index 000000000..c46abcc9d Binary files /dev/null and b/assets/share/combat/support/SUPPORT_SELECTED.4.png differ diff --git a/assets/share/combat/support/SUPPORT_SELECTED.SEARCH.png b/assets/share/combat/support/SUPPORT_SELECTED.SEARCH.png new file mode 100644 index 000000000..10a1f29b5 Binary files /dev/null and b/assets/share/combat/support/SUPPORT_SELECTED.SEARCH.png differ diff --git a/assets/share/combat/support/SUPPORT_SELECTED.png b/assets/share/combat/support/SUPPORT_SELECTED.png new file mode 100644 index 000000000..38ed41ddb Binary files /dev/null and b/assets/share/combat/support/SUPPORT_SELECTED.png differ diff --git a/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png b/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png index c540a448d..216c47be3 100644 Binary files a/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png and b/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_1.png b/assets/share/dungeon/ui/CALYX_WORLD_1.png new file mode 100644 index 000000000..5457292d2 Binary files /dev/null and b/assets/share/dungeon/ui/CALYX_WORLD_1.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_2.png b/assets/share/dungeon/ui/CALYX_WORLD_2.png new file mode 100644 index 000000000..3b3e3edb7 Binary files /dev/null and b/assets/share/dungeon/ui/CALYX_WORLD_2.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_3.png b/assets/share/dungeon/ui/CALYX_WORLD_3.png new file mode 100644 index 000000000..eeb73049b Binary files /dev/null and b/assets/share/dungeon/ui/CALYX_WORLD_3.png differ diff --git a/assets/share/dungeon/ui/LIST_LOADED_CHECK.png b/assets/share/dungeon/ui/LIST_LOADED_CHECK.png new file mode 100644 index 000000000..df938c00d Binary files /dev/null and b/assets/share/dungeon/ui/LIST_LOADED_CHECK.png differ diff --git a/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.png b/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.png index 89f5d74fb..7eb9ec332 100644 Binary files a/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.png and b/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.png differ diff --git a/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOCKED.png b/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOCKED.png new file mode 100644 index 000000000..70b03718e Binary files /dev/null and b/assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOCKED.png differ diff --git a/assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.2.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.2.png similarity index 100% rename from assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.2.png rename to assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.2.png diff --git a/assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.3.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.3.png new file mode 100644 index 000000000..8cf56e9f1 Binary files /dev/null and b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.3.png differ diff --git a/assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.SEARCH.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.SEARCH.png similarity index 100% rename from assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.SEARCH.png rename to assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.SEARCH.png diff --git a/assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.png similarity index 100% rename from assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.png rename to assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.png diff --git a/assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.2.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.2.png similarity index 100% rename from assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.2.png rename to assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.2.png diff --git a/assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.3.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.3.png new file mode 100644 index 000000000..02844f343 Binary files /dev/null and b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.3.png differ diff --git a/assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.SEARCH.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.SEARCH.png similarity index 100% rename from assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.SEARCH.png rename to assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.SEARCH.png diff --git a/assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.png b/assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.png similarity index 100% rename from assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.png rename to assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.png diff --git a/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.2.png b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.2.png new file mode 100644 index 000000000..8069245ec Binary files /dev/null and b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.2.png differ diff --git a/assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CHECK.png b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.png similarity index 100% rename from assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CHECK.png rename to assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.png diff --git a/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.2.png b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.2.png new file mode 100644 index 000000000..5cbeb0ef3 Binary files /dev/null and b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.2.png differ diff --git a/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.png b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.png new file mode 100644 index 000000000..aa5c2e4b8 Binary files /dev/null and b/assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.png differ diff --git a/assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CLICK.png b/assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CLICK.png deleted file mode 100644 index 770628c06..000000000 Binary files a/assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CLICK.png and /dev/null differ diff --git a/assets/share/forgotten_hall/ui/TELEPORT.png b/assets/share/forgotten_hall/ui/TELEPORT.png index 66cf16c00..bebf250e1 100644 Binary files a/assets/share/forgotten_hall/ui/TELEPORT.png and b/assets/share/forgotten_hall/ui/TELEPORT.png differ diff --git a/assets/share/freebies/support_reward/CAN_GET_REWARD.png b/assets/share/freebies/support_reward/CAN_GET_REWARD.png index 3a8c3074a..afaf00938 100644 Binary files a/assets/share/freebies/support_reward/CAN_GET_REWARD.png and b/assets/share/freebies/support_reward/CAN_GET_REWARD.png differ diff --git a/assets/share/freebies/support_reward/CLICKING_REWARD.png b/assets/share/freebies/support_reward/CLICKING_REWARD.png deleted file mode 100644 index e0b3c597a..000000000 Binary files a/assets/share/freebies/support_reward/CLICKING_REWARD.png and /dev/null differ diff --git a/assets/share/freebies/support_reward/IN_PROFILE.png b/assets/share/freebies/support_reward/IN_PROFILE.png index 2e0aadee8..b6392d7fd 100644 Binary files a/assets/share/freebies/support_reward/IN_PROFILE.png and b/assets/share/freebies/support_reward/IN_PROFILE.png differ diff --git a/assets/share/map/control/A_BUTTON.png b/assets/share/map/control/A_BUTTON.png index 46e8a9f15..b3596dff7 100644 Binary files a/assets/share/map/control/A_BUTTON.png and b/assets/share/map/control/A_BUTTON.png differ diff --git a/assets/share/map/control/E_BUTTON.png b/assets/share/map/control/E_BUTTON.png index 3fe31de38..5b6b9f73c 100644 Binary files a/assets/share/map/control/E_BUTTON.png and b/assets/share/map/control/E_BUTTON.png differ diff --git a/assets/share/map/control/RUN_BUTTON.png b/assets/share/map/control/RUN_BUTTON.png index d6e54c896..dd16067c3 100644 Binary files a/assets/share/map/control/RUN_BUTTON.png and b/assets/share/map/control/RUN_BUTTON.png differ diff --git a/assets/share/map/control/TECHNIQUE_POINT_1.png b/assets/share/map/control/TECHNIQUE_POINT_1.png index 30479efbe..ea6201eaa 100644 Binary files a/assets/share/map/control/TECHNIQUE_POINT_1.png and b/assets/share/map/control/TECHNIQUE_POINT_1.png differ diff --git a/assets/share/map/control/TECHNIQUE_POINT_2.png b/assets/share/map/control/TECHNIQUE_POINT_2.png index 76f3d7197..1c8b28ae6 100644 Binary files a/assets/share/map/control/TECHNIQUE_POINT_2.png and b/assets/share/map/control/TECHNIQUE_POINT_2.png differ diff --git a/assets/share/map/control/TECHNIQUE_POINT_3.png b/assets/share/map/control/TECHNIQUE_POINT_3.png index 0e2c7fa35..d388277ab 100644 Binary files a/assets/share/map/control/TECHNIQUE_POINT_3.png and b/assets/share/map/control/TECHNIQUE_POINT_3.png differ diff --git a/assets/share/map/control/TECHNIQUE_POINT_4.png b/assets/share/map/control/TECHNIQUE_POINT_4.png index 1adda0efa..d6d9e5bf3 100644 Binary files a/assets/share/map/control/TECHNIQUE_POINT_4.png and b/assets/share/map/control/TECHNIQUE_POINT_4.png differ diff --git a/assets/share/map/control/TECHNIQUE_POINT_5.png b/assets/share/map/control/TECHNIQUE_POINT_5.png index 5fcf8b4ba..f22c60117 100644 Binary files a/assets/share/map/control/TECHNIQUE_POINT_5.png and b/assets/share/map/control/TECHNIQUE_POINT_5.png differ diff --git a/assets/share/rogue/entry/OCR_WORLD.png b/assets/share/rogue/entry/OCR_WORLD.png index 51bb5f5f7..3a8746284 100644 Binary files a/assets/share/rogue/entry/OCR_WORLD.png and b/assets/share/rogue/entry/OCR_WORLD.png differ diff --git a/config/template.json b/config/template.json index 7dbb93c83..584323178 100644 --- a/config/template.json +++ b/config/template.json @@ -53,8 +53,8 @@ "Team": 1 }, "DungeonDaily": { - "CalyxGolden": "Calyx_Golden_Treasures", - "CalyxCrimson": "Calyx_Crimson_Erudition", + "CalyxGolden": "Calyx_Golden_Treasures_Jarilo_VI", + "CalyxCrimson": "Calyx_Crimson_Destruction_Herta_StorageZone", "StagnantShadow": "Stagnant_Shadow_Quanta", "CavernOfCorrosion": "Cavern_of_Corrosion_Path_of_Providence" }, @@ -179,6 +179,10 @@ "Weekly": { "Name": "Echo_of_War_Divine_Seed", "Team": 1 + }, + "DungeonSupport": { + "Use": "do_not_use", + "Character": "FirstCharacter" } }, "Rogue": { @@ -212,7 +216,8 @@ }, "Daemon": { "Daemon": { - "Enable": true + "Enable": true, + "AimClicker": "do_not_click" } } } \ No newline at end of file diff --git a/dev_tools/keyword_extract.py b/dev_tools/keyword_extract.py index dd53f1a6a..5b2cc2947 100644 --- a/dev_tools/keyword_extract.py +++ b/dev_tools/keyword_extract.py @@ -1,41 +1,16 @@ import itertools import os import re -import typing as t from collections import defaultdict -from functools import cache, cached_property +from functools import cache from hashlib import md5 +from dev_tools.keywords.base import TextMap, UI_LANGUAGES, replace_templates, text_to_variable from module.base.code_generator import CodeGenerator from module.config.utils import deep_get, read_file from module.exception import ScriptError from module.logger import logger -UI_LANGUAGES = ['cn', 'cht', 'en', 'jp', 'es'] - - -def text_to_variable(text): - text = re.sub("'s |s' ", '_', text) - text = re.sub('[ \-—:\'/•.]+', '_', text) - text = re.sub(r'[(),#"?!&%*]|', '', text) - # text = re.sub(r'[#_]?\d+(_times?)?', '', text) - text = re.sub(r'', '', text) - text = text.replace('é', 'e') - return text.strip('_') - - -def dungeon_name(name: str) -> str: - name = text_to_variable(name) - name = re.sub('Bud_of_(Memories|Aether|Treasures)', r'Calyx_Golden_\1', name) - name = re.sub('Bud_of_(.*)', r'Calyx_Crimson_\1', name).replace('Calyx_Crimson_Calyx_Crimson_', 'Calyx_Crimson_') - name = re.sub('Shape_of_(.*)', r'Stagnant_Shadow_\1', name) - name = re.sub('Path_of_(.*)', r'Cavern_of_Corrosion_Path_of_\1', name) - if name in ['Destruction_Beginning', 'End_of_the_Eternal_Freeze', 'Divine_Seed', 'Borehole_Planet_Old_Crater']: - name = f'Echo_of_War_{name}' - if name in ['The_Swarm_Disaster', 'Gold_and_Gears']: - name = f'Simulated_Universe_{name}' - return name - def blessing_name(name: str) -> str: name = text_to_variable(name) @@ -61,102 +36,12 @@ def convert_inner_character_to_keyword(name): return convert_dict.get(name, name) -class TextMap: - DATA_FOLDER = '' - - def __init__(self, lang: str): - self.lang = lang - - def __contains__(self, name: t.Union[int, str]) -> bool: - if isinstance(name, int) or (isinstance(name, str) and name.isdigit()): - return int(name) in self.data - return False - - @cached_property - def data(self) -> dict[int, str]: - if not os.path.exists(TextMap.DATA_FOLDER): - logger.critical('`TextMap.DATA_FOLDER` does not exist, please set it to your path to StarRailData') - exit(1) - file = os.path.join(TextMap.DATA_FOLDER, 'TextMap', f'TextMap{self.lang.upper()}.json') - data = {} - for id_, text in read_file(file).items(): - text = text.replace('\u00A0', '') - text = text.replace(r'{NICKNAME}', 'Trailblazer') - data[int(id_)] = text - return data - - def find(self, name: t.Union[int, str]) -> tuple[int, str]: - """ - Args: - name: - - Returns: - text id (hash in TextMap) - text - """ - if isinstance(name, int) or (isinstance(name, str) and name.isdigit()): - name = int(name) - try: - return name, self.data[name] - except KeyError: - pass - - name = str(name) - for row_id, row_name in self.data.items(): - if row_id >= 0 and row_name == name: - return row_id, row_name - for row_id, row_name in self.data.items(): - if row_name == name: - return row_id, row_name - logger.error(f'Cannot find name: "{name}" in language {self.lang}') - return 0, '' - - -def replace_templates(text: str) -> str: - """ - Replace templates in data to make sure it equals to what is shown in game - - Examples: - replace_templates("Complete Echo of War #4 time(s)") - == "Complete Echo of War 1 time(s)" - """ - text = re.sub(r'#4', '1', text) - text = re.sub(r'', '', text) - text = re.sub(r'', '', text) - return text - - class KeywordExtract: def __init__(self): self.text_map: dict[str, TextMap] = {lang: TextMap(lang) for lang in UI_LANGUAGES} self.text_map['cn'] = TextMap('chs') self.keywords_id: list[int] = [] - def iter_guide(self) -> t.Iterable[int]: - file = os.path.join(TextMap.DATA_FOLDER, './ExcelOutput/GameplayGuideData.json') - # visited = set() - temp_save = "" - for data in read_file(file).values(): - hash_ = deep_get(data, keys='Name.Hash') - _, name = self.find_keyword(hash_, lang='cn') - if '永屹之城遗秘' in name: # load after all forgotten hall to make sure the same order in Game UI - temp_save = hash_ - continue - if '忘却之庭' in name: - continue - # if name in visited: - # continue - # visited.add(name) - yield hash_ - yield temp_save - # Consider rogue DLC as a dungeon - yield '寰宇蝗灾' - yield '黄金与机械' - # 'Memory of Chaos' is not a real dungeon, but represents a group - yield '混沌回忆' - yield '天艟求仙迷航录' - yield '永屹之城遗秘' - def find_keyword(self, keyword, lang) -> tuple[int, str]: """ Args: @@ -388,7 +273,7 @@ class KeywordExtract: gen.ObjectAttr(key='name', value=name) for lang in UI_LANGUAGES: character_names = ' / '.join([ - self.find_keyword(c[0], lang)[1] + replace_templates(self.find_keyword(c[0], lang)[1]) for c in characters ]) damage_type = self.find_keyword(characters[0][1], lang)[1] @@ -422,47 +307,14 @@ class KeywordExtract: self.clear_keywords() def generate_assignments(self): - self.load_keywords(['空间站特派']) - self.write_keywords( - keyword_class='AssignmentEventGroup', - output_file='./tasks/assignment/keywords/event_group.py' - ) - for file_name, class_name, output_file in ( - ('ExpeditionGroup.json', 'AssignmentGroup', './tasks/assignment/keywords/group.py'), - ('ExpeditionData.json', 'AssignmentEntry', './tasks/assignment/keywords/entry.py'), - ('ActivityExpedition.json', 'AssignmentEventEntry', './tasks/assignment/keywords/event_entry.py'), - ): - file = os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', file_name) - self.load_keywords(deep_get(data, 'Name.Hash') for data in read_file(file).values()) - self.write_keywords(keyword_class=class_name, output_file=output_file) + from dev_tools.keywords.assignment import GenerateAssignment + GenerateAssignment()() def generate_map_planes(self): - planes = { - 'Special': ['黑塔的办公室', '锋芒崭露'], - 'Rogue': [ '区域-战斗', '区域-事件', '区域-遭遇', '区域-休整', '区域-精英', '区域-首领', '区域-交易'], - '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') - self.load_keywords(['Herta Space Station', 'Jarilo-VI', 'The Xianzhou Luofu'], lang='en') - self.write_keywords(keyword_class='MapWorld', output_file='./tasks/map/keywords/world.py') + from dev_tools.keywords.map_world import GenerateMapWorld + GenerateMapWorld()() + from dev_tools.keywords.map_plane import GenerateMapPlane + GenerateMapPlane()() def generate_character_keywords(self): self.load_character_name_keywords() @@ -493,6 +345,9 @@ class KeywordExtract: gen.DictItem(key=character, value=height) gen.write('./tasks/character/keywords/height.py') + self.load_keywords(['物理', '火', '冰', '雷', '风', '量子', '虚数'], lang='cn') + self.write_keywords(keyword_class='CombatType', output_file='./tasks/character/keywords/combat_type.py') + def generate_battle_pass_quests(self): battle_pass_quests = read_file(os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', 'BattlePassConfig.json')) latest_quests = list(battle_pass_quests.values())[-1] @@ -700,10 +555,11 @@ class KeywordExtract: self.load_keywords(['领取', '追踪']) self.write_keywords(keyword_class='BattlePassQuestState', output_file='./tasks/battle_pass/keywords/quest_state.py') - self.load_keywords(list(self.iter_guide())) - self.write_keywords(keyword_class='DungeonList', output_file='./tasks/dungeon/keywords/dungeon.py', - text_convert=dungeon_name) - self.load_keywords(['传送', '追踪']) + self.generate_map_planes() + self.generate_character_keywords() + from dev_tools.keywords.dungeon_list import GenerateDungeonList + GenerateDungeonList()() + self.load_keywords(['进入', '传送', '追踪']) self.write_keywords(keyword_class='DungeonEntrance', output_file='./tasks/dungeon/keywords/dungeon_entrance.py') self.generate_shadow_with_characters() self.load_keywords(['奖励', '任务', ]) @@ -713,8 +569,6 @@ class KeywordExtract: output_file='./tasks/battle_pass/keywords/mission_tab.py') self.generate_assignments() self.generate_forgotten_hall_stages() - self.generate_map_planes() - self.generate_character_keywords() self.generate_daily_quests() self.generate_battle_pass_quests() self.load_keywords(['养成材料', '光锥', '遗器', '其他材料', '消耗品', '任务', '贵重物']) diff --git a/dev_tools/keywords/assignment.py b/dev_tools/keywords/assignment.py new file mode 100644 index 000000000..30dadcb25 --- /dev/null +++ b/dev_tools/keywords/assignment.py @@ -0,0 +1,123 @@ +from functools import cache +from typing import Iterable + +from dev_tools.keywords.base import UI_LANGUAGES, GenerateKeyword +from module.config.utils import deep_get + + +@cache +def get_assignment_entry_data(): + """ + Returns: + dict: key - assignment text_id + value - text_id of reward items + """ + expedition_namehash_to_id = { + deep_get(expedition, 'Name.Hash'): deep_get(expedition, 'ExpeditionID') + for expedition in GenerateKeyword.read_file('./ExcelOutput/ExpeditionData.json').values() + } + expedition_id_to_reward_id = { + deep_get(expedition, '4.2.ExpeditionID'): deep_get(expedition, '4.2.RewardID') + for expedition in GenerateKeyword.read_file('./ExcelOutput/ExpeditionReward.json').values() + } + reward_id_to_item_ids = { + deep_get(reward, 'RewardID'): [ + v for k, v in reward.items() + if k.startswith('ItemID') + ] + for reward in GenerateKeyword.read_file('./ExcelOutput/RewardData.json').values() + } + item_id_to_namehash = { + deep_get(item, 'ID'): deep_get(item, 'ItemName.Hash') + for item in GenerateKeyword.read_file('./ExcelOutput/ItemConfig.json').values() + } + item_name_remap = { + '旅情见闻': '角色经验材料', + '稀薄以太': '光锥经验材料' + } + ret = dict() + for expedition_namehash, expedition_id in expedition_namehash_to_id.items(): + reward_id = expedition_id_to_reward_id[expedition_id] + item_ids = reward_id_to_item_ids[reward_id] + item_names = [item_id_to_namehash[x] for x in item_ids] + if len(item_names) == 1: + item = GenerateKeyword.find_keyword(item_names[0], lang='cn')[1] + if item in item_name_remap: + item_names = [GenerateKeyword.find_keyword( + item_name_remap[item], lang='cn')[0]] + ret[expedition_namehash] = item_names + return ret + + +class GenerateAssignment(GenerateKeyword): + def generate(self): + GenerateAssignmentGroup()() + GenerateAssignmentEntry()() + GenerateAssignmentEventGroup()() + GenerateAssignmentEventEntry()() + GenerateAssignmentEntryDetailed()() + + +class GenerateAssignmentGroup(GenerateKeyword): + output_file = './tasks/assignment/keywords/group.py' + + def iter_keywords(self) -> Iterable[dict]: + for group in self.read_file('./ExcelOutput/ExpeditionGroup.json').values(): + yield dict(text_id=deep_get(group, 'Name.Hash')) + + +class GenerateAssignmentEntry(GenerateKeyword): + output_file = './tasks/assignment/keywords/entry.py' + + def iter_keywords(self) -> Iterable[dict]: + for k in get_assignment_entry_data().keys(): + yield dict(text_id=k) + + +class GenerateAssignmentEntryDetailed(GenerateKeyword): + output_file = './tasks/assignment/keywords/entry_detailed.py' + + def iter_keywords(self) -> Iterable[dict]: + for assignment_id, reward_ids in get_assignment_entry_data().items(): + yield dict( + text_id=assignment_id, + reward_ids=reward_ids + ) + + def iter_rows(self) -> Iterable[dict]: + for keyword in super().iter_rows(): + reward_ids = keyword.pop('reward_ids') + for lang in UI_LANGUAGES: + assignment_name = keyword[lang] + reward_name = ' & '.join( + self.find_keyword(reward_id, lang=lang)[1] + for reward_id in reward_ids + ) + name_format = '{reward_name} ({assignment_name})' if lang in { + 'en', 'es'} else '{reward_name}({assignment_name})' + keyword[lang] = name_format.format( + reward_name=reward_name, + assignment_name=assignment_name + ) + yield keyword + + +class GenerateAssignmentEventGroup(GenerateKeyword): + output_file = './tasks/assignment/keywords/event_group.py' + + def iter_keywords(self) -> Iterable[dict]: + yield dict(text_id=self.find_keyword('空间站特派', lang='cn')[0]) + + +class GenerateAssignmentEventEntry(GenerateKeyword): + output_file = './tasks/assignment/keywords/event_entry.py' + + def iter_keywords(self) -> Iterable[dict]: + for expedition in self.read_file('./ExcelOutput/ActivityExpedition.json').values(): + yield dict(text_id=deep_get(expedition, 'Name.Hash')) + + +if __name__ == "__main__": + from dev_tools.keywords.base import TextMap + TextMap.DATA_FOLDER = '../StarRailData' + GenerateAssignment()() diff --git a/dev_tools/keywords/base.py b/dev_tools/keywords/base.py new file mode 100644 index 000000000..e44f0ac61 --- /dev/null +++ b/dev_tools/keywords/base.py @@ -0,0 +1,192 @@ +import os +import re +import typing as t +from functools import cached_property + +from module.base.code_generator import CodeGenerator +from module.config.utils import read_file +from module.logger import logger + +UI_LANGUAGES = ['cn', 'cht', 'en', 'jp', 'es'] + + +class TextMap: + DATA_FOLDER = '' + + def __init__(self, lang: str): + self.lang = lang + + def __contains__(self, name: t.Union[int, str]) -> bool: + if isinstance(name, int) or (isinstance(name, str) and name.isdigit()): + return int(name) in self.data + return False + + @cached_property + def data(self) -> dict[int, str]: + if not os.path.exists(TextMap.DATA_FOLDER): + logger.critical('`TextMap.DATA_FOLDER` does not exist, please set it to your path to StarRailData') + exit(1) + file = os.path.join(TextMap.DATA_FOLDER, 'TextMap', f'TextMap{self.lang.upper()}.json') + data = {} + for id_, text in read_file(file).items(): + text = text.replace('\u00A0', '') + text = text.replace(r'{NICKNAME}', 'Trailblazer') + data[int(id_)] = text + return data + + def find(self, name: t.Union[int, str]) -> tuple[int, str]: + """ + Args: + name: + + Returns: + text id (hash in TextMap) + text + """ + if isinstance(name, int) or (isinstance(name, str) and name.isdigit()): + name = int(name) + try: + return name, self.data[name] + except KeyError: + pass + + name = str(name) + for row_id, row_name in self.data.items(): + if row_id >= 0 and row_name == name: + return row_id, row_name + for row_id, row_name in self.data.items(): + if row_name == name: + return row_id, row_name + logger.error(f'Cannot find name: "{name}" in language {self.lang}') + return 0, '' + + +def text_to_variable(text): + text = re.sub("'s |s' ", '_', text) + text = re.sub(r'[ \-—:\'/•.]+', '_', text) + text = re.sub(r'[(),#"?!&%*]|', '', text) + # text = re.sub(r'[#_]?\d+(_times?)?', '', text) + text = re.sub(r'', '', text) + text = text.replace('é', 'e') + return text.strip('_') + + +def replace_templates(text: str) -> str: + """ + Replace templates in data to make sure it equals to what is shown in game + + Examples: + replace_templates("Complete Echo of War #4 time(s)") + == "Complete Echo of War 1 time(s)" + """ + text = re.sub(r'#4', '1', text) + text = re.sub(r'', '', text) + text = re.sub(r'', '', text) + text = re.sub(r'{.*?}', '', text) + return text + + +class GenerateKeyword: + text_map: dict[str, TextMap] = {lang: TextMap(lang) for lang in UI_LANGUAGES} + text_map['cn'] = TextMap('chs') + + @staticmethod + def read_file(file: str) -> dict: + """ + Args: + file: ./ExcelOutput/GameplayGuideData.json + + Returns: + dict: + """ + file = os.path.join(TextMap.DATA_FOLDER, file) + return read_file(file) + + @classmethod + def find_keyword(cls, keyword, lang) -> tuple[int, str]: + """ + Args: + keyword: text string or text id + lang: Language to find + + Returns: + text id (hash in TextMap) + text + """ + text_map = cls.text_map[lang] + return text_map.find(keyword) + + output_file = '' + + def __init__(self): + self.gen = CodeGenerator() + self.keyword_class = self.__class__.__name__.removeprefix('Generate') + self.keyword_index = 0 + self.keyword_format = { + 'id': 0, + 'name': 'Unnamed_Keyword' + } + for lang in UI_LANGUAGES: + self.keyword_format[lang] = '' + + def gen_import(self): + self.gen.Import( + f""" + from .classes import {self.keyword_class} + """ + ) + + def iter_keywords(self) -> t.Iterable[dict]: + """ + Yields + dict: {'text_id': 123456, 'any_attr': 1} + """ + pass + + def convert_name(self, text: str, keyword: dict) -> str: + return text_to_variable(replace_templates(text)) + + def convert_keyword(self, text: str, lang: str) -> str: + return replace_templates(text) + + def iter_rows(self) -> t.Iterable[dict]: + for keyword in self.iter_keywords(): + keyword = self.format_keywords(keyword) + yield keyword + + def format_keywords(self, keyword: dict) -> dict | None: + base = self.keyword_format.copy() + text_id = keyword.pop('text_id') + if text_id is None: + return + # id + self.keyword_index += 1 + base['id'] = self.keyword_index + # Attrs + base.update(keyword) + # Name + _, name = self.find_keyword(text_id, lang='en') + name = self.convert_name(name, keyword=base) + base['name'] = name + # Translations + for lang in UI_LANGUAGES: + value = self.find_keyword(text_id, lang=lang)[1] + value = self.convert_keyword(value, lang=lang) + base[lang] = value + return base + + def generate(self): + self.gen_import() + self.gen.CommentAutoGenerage('dev_tools.keyword_extract') + + for keyword in self.iter_rows(): + with self.gen.Object(key=keyword['name'], object_class=self.keyword_class): + for key, value in keyword.items(): + self.gen.ObjectAttr(key, value) + + if self.output_file: + print(f'Write {self.output_file}') + self.gen.write(self.output_file) + + def __call__(self, *args, **kwargs): + self.generate() diff --git a/dev_tools/keywords/dungeon_list.py b/dev_tools/keywords/dungeon_list.py new file mode 100644 index 000000000..d18451619 --- /dev/null +++ b/dev_tools/keywords/dungeon_list.py @@ -0,0 +1,108 @@ +import re +import typing as t + +from dev_tools.keywords.base import GenerateKeyword, text_to_variable +from module.base.decorator import cached_property +from module.config.utils import deep_get + + +def dungeon_name(name: str) -> str: + name = text_to_variable(name) + name = re.sub('Bud_of_(Memories|Aether|Treasures)', r'Calyx_Golden_\1', name) + name = re.sub('Bud_of_(.*)', r'Calyx_Crimson_\1', name).replace('Calyx_Crimson_Calyx_Crimson_', 'Calyx_Crimson_') + name = re.sub('Shape_of_(.*)', r'Stagnant_Shadow_\1', name) + name = re.sub('Path_of_(.*)', r'Cavern_of_Corrosion_Path_of_\1', name) + if name in ['Destruction_Beginning', 'End_of_the_Eternal_Freeze', 'Divine_Seed', 'Borehole_Planet_Old_Crater']: + name = f'Echo_of_War_{name}' + if name in ['The_Swarm_Disaster', 'Gold_and_Gears']: + name = f'Simulated_Universe_{name}' + return name + + +class GenerateDungeonList(GenerateKeyword): + output_file = './tasks/dungeon/keywords/dungeon.py' + + @cached_property + def data(self): + return self.read_file('./ExcelOutput/GameplayGuideData.json') + + def iter_keywords(self) -> t.Iterable[dict]: + for keyword in self.iter_dungeon(): + if isinstance(keyword, str): + yield dict( + text_id=self.find_keyword(keyword, lang='cn')[0], + plane_id=-1, + ) + else: + yield keyword + + def iter_dungeon(self): + temp_save = "" + for data in self.data.values(): + text_id = deep_get(data, keys='Name.Hash') + plane_id = deep_get(data, 'MapEntranceID', 0) + _, name = self.find_keyword(text_id, lang='cn') + if '永屹之城遗秘' in name: # load after all forgotten hall to make sure the same order in Game UI + temp_save = text_id + continue + if '忘却之庭' in name: + continue + yield dict( + text_id=text_id, + plane_id=plane_id, + ) + if temp_save: + yield temp_save + # Consider rogue DLC as a dungeon + yield '寰宇蝗灾' + yield '黄金与机械' + # 'Memory of Chaos' is not a real dungeon, but represents a group + yield '混沌回忆' + yield '天艟求仙迷航录' + yield '永屹之城遗秘' + + def convert_name(self, text: str, keyword: dict) -> str: + text = super().convert_name(text, keyword=keyword) + text = dungeon_name(text) + + # Add plane suffix + from tasks.map.keywords import MapPlane + + if text.startswith('Calyx_Crimson'): + plane = MapPlane.find_plane_id(keyword['plane_id']) + text = f'{text}_{plane.name}' + return text + + def convert_keyword(self, text: str, lang: str) -> str: + text = super().convert_keyword(text, lang=lang) + # Bud of Memories (Jarilo-Ⅵ) + # Use roman numbers instead + text = re.sub(r'-[VⅤ][IⅠ]', '-Ⅵ', text) + + return text + + def iter_rows(self) -> t.Iterable[dict]: + dungeons = list(super().iter_rows()) + calyx = [] + order = [ + 'Calyx_Golden', + 'Calyx_Crimson_Destruction', + 'Calyx_Crimson_Preservation', + 'Calyx_Crimson_The_Hunt', + 'Calyx_Crimson_Abundance', + 'Calyx_Crimson_Erudition', + 'Calyx_Crimson_Harmony', + 'Calyx_Crimson_Nihility', + ] + for keyword in order: + condition = lambda x: x['name'].startswith(keyword) + calyx += [d for d in dungeons if condition(d)] + dungeons = [d for d in dungeons if not condition(d)] + dungeons = calyx + dungeons + + self.keyword_index = 0 + for row in dungeons: + # Re-sort ID + self.keyword_index += 1 + row['id'] = self.keyword_index + yield row diff --git a/dev_tools/keywords/map_plane.py b/dev_tools/keywords/map_plane.py new file mode 100644 index 000000000..dec382cff --- /dev/null +++ b/dev_tools/keywords/map_plane.py @@ -0,0 +1,70 @@ +import typing as t + +from dev_tools.keywords.base import GenerateKeyword +from module.base.decorator import cached_property +from module.config.utils import deep_get + + +class GenerateMapPlane(GenerateKeyword): + output_file = './tasks/map/keywords/plane.py' + + @cached_property + def data(self): + return self.read_file('./ExcelOutput/AreaMapConfig.json') + + def iter_planes(self) -> t.Iterable[dict]: + for plane_id, data in self.data.items(): + plane_id = int(plane_id) + world_id = int(str(plane_id)[-5]) + sort_id = int(deep_get(data, 'MenuSortID', 0)) + text_id = deep_get(data, 'Name.Hash') + yield dict( + text_id=text_id, + world_id=world_id, + plane_id=plane_id, + sort_id=sort_id, + ) + + def iter_keywords(self) -> t.Iterable[dict]: + """ + 1010201 + ^^ floor + ^^ plane + ^ world + """ + def to_id(name): + return self.find_keyword(name, lang='cn')[0] + + domains = ['黑塔的办公室', '锋芒崭露'] + for index, domain in enumerate(domains): + yield dict( + text_id=to_id(domain), + world_id=-1, + plane_id=index + 1, + ) + domains = ['区域-战斗', '区域-事件', '区域-遭遇', '区域-休整', '区域-精英', '区域-首领', '区域-交易'] + for index, domain in enumerate(domains): + yield dict( + text_id=to_id(domain), + world_id=-2, + plane_id=index + 1, + ) + + keywords = sorted(self.iter_planes(), key=lambda x: (x['world_id'], x['sort_id'])) + for keyword in keywords: + keyword.pop('sort_id') + yield keyword + + def convert_name(self, text: str, keyword: dict) -> str: + text = super().convert_name(text, keyword=keyword) + text = text.replace('_', '') + + from tasks.map.keywords import MapWorld + world = MapWorld.find_world_id(keyword['world_id']) + if world is None: + if text.startswith('Domain'): + return f'Rogue_{text}' + else: + return f'Special_{text}' + else: + return f'{world.short_name}_{text}' diff --git a/dev_tools/keywords/map_world.py b/dev_tools/keywords/map_world.py new file mode 100644 index 000000000..2adde7341 --- /dev/null +++ b/dev_tools/keywords/map_world.py @@ -0,0 +1,33 @@ +import typing as t + +from dev_tools.keywords.base import GenerateKeyword + + +class GenerateMapWorld(GenerateKeyword): + output_file = './tasks/map/keywords/world.py' + + def iter_keywords(self) -> t.Iterable[dict]: + + def to_id(name): + return self.find_keyword(name, lang='en')[0] + + yield dict( + text_id=to_id('Herta Space Station'), + world_id=0, + short_name='Herta' + ) + yield dict( + text_id=to_id('Jarilo-VI'), + world_id=1, + short_name='Jarilo' + ) + yield dict( + text_id=to_id('The Xianzhou Luofu'), + world_id=2, + short_name='Luofu' + ) + yield dict( + text_id=to_id('Penacony'), + world_id=3, + short_name='Penacony' + ) \ No newline at end of file diff --git a/dev_tools/screenshot.py b/dev_tools/screenshot.py index 90ce49bd0..746be65d4 100644 --- a/dev_tools/screenshot.py +++ b/dev_tools/screenshot.py @@ -50,12 +50,12 @@ def handle_sensitive_info(image): _ = EmptyConnection() name = input( - '输入alas配置文件名称,或者模拟器serial,或者模拟器端口号: (默认输入 "alas"):\n' - '例如:"alas", "127.0.0.1:16384", "7555"\n' + '输入src配置文件名称,或者模拟器serial,或者模拟器端口号: (默认输入 "src"):\n' + '例如:"src", "127.0.0.1:16384", "7555"\n' ) name = name.strip().strip('"').strip() if not name: - name = 'alas' + name = 'src' if name.isdigit(): name = f'127.0.0.1:{name}' if name in alas_instance(): diff --git a/module/base/button.py b/module/base/button.py index 0f9671a32..b0e057ee5 100644 --- a/module/base/button.py +++ b/module/base/button.py @@ -306,6 +306,34 @@ class ButtonWrapper(Resource): for b in self.iter_buttons(): b.search = area + def set_search_offset(self, offset): + """ + Compatible with Alas’ `offset` attribute + In ALAS: + if self.appear(BUTTON, offset=(20, 20)): + pass + In SRC: + BUTTON.set_search_offset((20, 20)) + if self.appear(BUTTON): + pass + Note that `search` attribute will be set, and it's irreversible. + + Args: + offset (tuple): (x, y) or (left, up, right, bottom) + """ + if len(offset) == 2: + left, up, right, bottom = -offset[0], -offset[1], offset[0], offset[1] + else: + left, up, right, bottom = offset + for b in self.iter_buttons(): + upper_left_x, upper_left_y, bottom_right_x, bottom_right_y = b.area + b.search = ( + upper_left_x + left, + upper_left_y + up, + bottom_right_x + right, + bottom_right_y + bottom, + ) + class ClickButton: def __init__(self, area, button=None, name='CLICK_BUTTON'): diff --git a/module/config/argument/args.json b/module/config/argument/args.json index f6c30b185..4bc53524d 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -221,30 +221,41 @@ "type": "select", "value": "Calyx_Golden_Treasures", "option": [ - "Calyx_Golden_Memories", - "Calyx_Golden_Aether", - "Calyx_Golden_Treasures", - "Calyx_Crimson_Destruction", - "Calyx_Crimson_Preservation", - "Calyx_Crimson_The_Hunt", - "Calyx_Crimson_Abundance", - "Calyx_Crimson_Erudition", - "Calyx_Crimson_Harmony", - "Calyx_Crimson_Nihility", - "Stagnant_Shadow_Quanta", - "Stagnant_Shadow_Gust", - "Stagnant_Shadow_Fulmination", - "Stagnant_Shadow_Blaze", + "Calyx_Golden_Memories_Jarilo_VI", + "Calyx_Golden_Memories_The_Xianzhou_Luofu", + "Calyx_Golden_Memories_Penacony", + "Calyx_Golden_Aether_Jarilo_VI", + "Calyx_Golden_Aether_The_Xianzhou_Luofu", + "Calyx_Golden_Aether_Penacony", + "Calyx_Golden_Treasures_Jarilo_VI", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu", + "Calyx_Golden_Treasures_Penacony", + "Calyx_Crimson_Destruction_Herta_StorageZone", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape", + "Calyx_Crimson_Preservation_Herta_SupplyZone", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass", + "Calyx_Crimson_Erudition_Jarilo_RivetTown", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape", + "Calyx_Crimson_Nihility_Jarilo_GreatMine", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission", "Stagnant_Shadow_Spike", - "Stagnant_Shadow_Rime", - "Stagnant_Shadow_Mirage", - "Stagnant_Shadow_Icicle", - "Stagnant_Shadow_Doom", - "Stagnant_Shadow_Puppetry", - "Stagnant_Shadow_Abomination", - "Stagnant_Shadow_Scorch", - "Stagnant_Shadow_Celestial", "Stagnant_Shadow_Perdition", + "Stagnant_Shadow_Blaze", + "Stagnant_Shadow_Scorch", + "Stagnant_Shadow_Rime", + "Stagnant_Shadow_Icicle", + "Stagnant_Shadow_Nectar", + "Stagnant_Shadow_Fulmination", + "Stagnant_Shadow_Doom", + "Stagnant_Shadow_Gust", + "Stagnant_Shadow_Celestial", + "Stagnant_Shadow_Quanta", + "Stagnant_Shadow_Abomination", + "Stagnant_Shadow_Roast", + "Stagnant_Shadow_Mirage", + "Stagnant_Shadow_Puppetry", "Cavern_of_Corrosion_Path_of_Gelid_Wind", "Cavern_of_Corrosion_Path_of_Jabbing_Punch", "Cavern_of_Corrosion_Path_of_Drifting", @@ -252,7 +263,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn", "Cavern_of_Corrosion_Path_of_Conflagration", "Cavern_of_Corrosion_Path_of_Elixir_Seekers", - "Cavern_of_Corrosion_Path_of_Darkness" + "Cavern_of_Corrosion_Path_of_Darkness", + "Cavern_of_Corrosion_Path_of_Dreamdive" ] }, "NameAtDoubleCalyx": { @@ -260,16 +272,25 @@ "value": "Calyx_Golden_Treasures", "option": [ "do_not_participate", - "Calyx_Golden_Memories", - "Calyx_Golden_Aether", - "Calyx_Golden_Treasures", - "Calyx_Crimson_Destruction", - "Calyx_Crimson_Preservation", - "Calyx_Crimson_The_Hunt", - "Calyx_Crimson_Abundance", - "Calyx_Crimson_Erudition", - "Calyx_Crimson_Harmony", - "Calyx_Crimson_Nihility" + "Calyx_Golden_Memories_Jarilo_VI", + "Calyx_Golden_Memories_The_Xianzhou_Luofu", + "Calyx_Golden_Memories_Penacony", + "Calyx_Golden_Aether_Jarilo_VI", + "Calyx_Golden_Aether_The_Xianzhou_Luofu", + "Calyx_Golden_Aether_Penacony", + "Calyx_Golden_Treasures_Jarilo_VI", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu", + "Calyx_Golden_Treasures_Penacony", + "Calyx_Crimson_Destruction_Herta_StorageZone", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape", + "Calyx_Crimson_Preservation_Herta_SupplyZone", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass", + "Calyx_Crimson_Erudition_Jarilo_RivetTown", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape", + "Calyx_Crimson_Nihility_Jarilo_GreatMine", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission" ] }, "NameAtDoubleRelic": { @@ -284,7 +305,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn", "Cavern_of_Corrosion_Path_of_Conflagration", "Cavern_of_Corrosion_Path_of_Elixir_Seekers", - "Cavern_of_Corrosion_Path_of_Darkness" + "Cavern_of_Corrosion_Path_of_Darkness", + "Cavern_of_Corrosion_Path_of_Dreamdive" ] }, "Team": { @@ -306,26 +328,35 @@ "DungeonDaily": { "CalyxGolden": { "type": "select", - "value": "Calyx_Golden_Treasures", + "value": "Calyx_Golden_Treasures_Jarilo_VI", "option": [ "do_not_achieve", - "Calyx_Golden_Memories", - "Calyx_Golden_Aether", - "Calyx_Golden_Treasures" + "Calyx_Golden_Memories_Jarilo_VI", + "Calyx_Golden_Memories_The_Xianzhou_Luofu", + "Calyx_Golden_Memories_Penacony", + "Calyx_Golden_Aether_Jarilo_VI", + "Calyx_Golden_Aether_The_Xianzhou_Luofu", + "Calyx_Golden_Aether_Penacony", + "Calyx_Golden_Treasures_Jarilo_VI", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu", + "Calyx_Golden_Treasures_Penacony" ] }, "CalyxCrimson": { "type": "select", - "value": "Calyx_Crimson_Erudition", + "value": "Calyx_Crimson_Destruction_Herta_StorageZone", "option": [ "do_not_achieve", - "Calyx_Crimson_Destruction", - "Calyx_Crimson_Preservation", - "Calyx_Crimson_The_Hunt", - "Calyx_Crimson_Abundance", - "Calyx_Crimson_Erudition", - "Calyx_Crimson_Harmony", - "Calyx_Crimson_Nihility" + "Calyx_Crimson_Destruction_Herta_StorageZone", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape", + "Calyx_Crimson_Preservation_Herta_SupplyZone", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass", + "Calyx_Crimson_Erudition_Jarilo_RivetTown", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape", + "Calyx_Crimson_Nihility_Jarilo_GreatMine", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission" ] }, "StagnantShadow": { @@ -333,20 +364,22 @@ "value": "Stagnant_Shadow_Quanta", "option": [ "do_not_achieve", - "Stagnant_Shadow_Quanta", - "Stagnant_Shadow_Gust", - "Stagnant_Shadow_Fulmination", - "Stagnant_Shadow_Blaze", "Stagnant_Shadow_Spike", - "Stagnant_Shadow_Rime", - "Stagnant_Shadow_Mirage", - "Stagnant_Shadow_Icicle", - "Stagnant_Shadow_Doom", - "Stagnant_Shadow_Puppetry", - "Stagnant_Shadow_Abomination", + "Stagnant_Shadow_Perdition", + "Stagnant_Shadow_Blaze", "Stagnant_Shadow_Scorch", + "Stagnant_Shadow_Rime", + "Stagnant_Shadow_Icicle", + "Stagnant_Shadow_Nectar", + "Stagnant_Shadow_Fulmination", + "Stagnant_Shadow_Doom", + "Stagnant_Shadow_Gust", "Stagnant_Shadow_Celestial", - "Stagnant_Shadow_Perdition" + "Stagnant_Shadow_Quanta", + "Stagnant_Shadow_Abomination", + "Stagnant_Shadow_Roast", + "Stagnant_Shadow_Mirage", + "Stagnant_Shadow_Puppetry" ] }, "CavernOfCorrosion": { @@ -361,7 +394,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn", "Cavern_of_Corrosion_Path_of_Conflagration", "Cavern_of_Corrosion_Path_of_Elixir_Seekers", - "Cavern_of_Corrosion_Path_of_Darkness" + "Cavern_of_Corrosion_Path_of_Darkness", + "Cavern_of_Corrosion_Path_of_Dreamdive" ] } }, @@ -384,11 +418,13 @@ "Arlan", "Asta", "Bailu", + "BlackSwan", "Blade", "Bronya", "Clara", "DanHeng", "DanHengImbibitorLunae", + "DrRatio", "FuXuan", "Gepard", "Guinaifen", @@ -404,6 +440,7 @@ "Luocha", "Lynx", "March7th", + "Misha", "Natasha", "Pela", "Qingque", @@ -412,6 +449,7 @@ "Seele", "Serval", "SilverWolf", + "Sparkle", "Sushang", "Tingyun", "TopazNumby", @@ -1020,6 +1058,8 @@ "Born_to_Obey", "Root_Out_the_Turpitude", "Fire_Lord_Inflames_Blades_of_War", + "A_Startling_Night_Terror", + "Tranquility_of_Vimala_bhumi", "Nameless_Land_Nameless_People", "Akashic_Records", "The_Invisible_Hand", @@ -1028,7 +1068,9 @@ "The_Land_of_Gold", "The_Blossom_in_the_Storm", "Legend_of_the_Puppet_Master", - "The_Wages_of_Humanity" + "The_Wages_of_Humanity", + "Fragments_of_Illusory_Dreams", + "Scalpel_and_Screwdriver" ] }, "Name_2": { @@ -1041,6 +1083,8 @@ "Born_to_Obey", "Root_Out_the_Turpitude", "Fire_Lord_Inflames_Blades_of_War", + "A_Startling_Night_Terror", + "Tranquility_of_Vimala_bhumi", "Nameless_Land_Nameless_People", "Akashic_Records", "The_Invisible_Hand", @@ -1049,7 +1093,9 @@ "The_Land_of_Gold", "The_Blossom_in_the_Storm", "Legend_of_the_Puppet_Master", - "The_Wages_of_Humanity" + "The_Wages_of_Humanity", + "Fragments_of_Illusory_Dreams", + "Scalpel_and_Screwdriver" ] }, "Name_3": { @@ -1062,6 +1108,8 @@ "Born_to_Obey", "Root_Out_the_Turpitude", "Fire_Lord_Inflames_Blades_of_War", + "A_Startling_Night_Terror", + "Tranquility_of_Vimala_bhumi", "Nameless_Land_Nameless_People", "Akashic_Records", "The_Invisible_Hand", @@ -1070,7 +1118,9 @@ "The_Land_of_Gold", "The_Blossom_in_the_Storm", "Legend_of_the_Puppet_Master", - "The_Wages_of_Humanity" + "The_Wages_of_Humanity", + "Fragments_of_Illusory_Dreams", + "Scalpel_and_Screwdriver" ] }, "Name_4": { @@ -1083,6 +1133,8 @@ "Born_to_Obey", "Root_Out_the_Turpitude", "Fire_Lord_Inflames_Blades_of_War", + "A_Startling_Night_Terror", + "Tranquility_of_Vimala_bhumi", "Nameless_Land_Nameless_People", "Akashic_Records", "The_Invisible_Hand", @@ -1091,7 +1143,9 @@ "The_Land_of_Gold", "The_Blossom_in_the_Storm", "Legend_of_the_Puppet_Master", - "The_Wages_of_Humanity" + "The_Wages_of_Humanity", + "Fragments_of_Illusory_Dreams", + "Scalpel_and_Screwdriver" ] }, "Duration": { @@ -1251,6 +1305,68 @@ 9 ] } + }, + "DungeonSupport": { + "Use": { + "type": "select", + "value": "do_not_use", + "option": [ + "always_use", + "do_not_use" + ] + }, + "Character": { + "type": "select", + "value": "FirstCharacter", + "option": [ + "FirstCharacter", + "Argenti", + "Arlan", + "Asta", + "Bailu", + "BlackSwan", + "Blade", + "Bronya", + "Clara", + "DanHeng", + "DanHengImbibitorLunae", + "DrRatio", + "FuXuan", + "Gepard", + "Guinaifen", + "Hanya", + "Herta", + "Himeko", + "Hook", + "Huohuo", + "JingYuan", + "Jingliu", + "Kafka", + "Luka", + "Luocha", + "Lynx", + "March7th", + "Misha", + "Natasha", + "Pela", + "Qingque", + "RuanMei", + "Sampo", + "Seele", + "Serval", + "SilverWolf", + "Sparkle", + "Sushang", + "Tingyun", + "TopazNumby", + "TrailblazerDestruction", + "TrailblazerPreservation", + "Welt", + "Xueyi", + "Yanqing", + "Yukong" + ] + } } }, "Rogue": { @@ -1402,6 +1518,16 @@ "option_bold": [ true ] + }, + "AimClicker": { + "type": "select", + "value": "do_not_click", + "option": [ + "item_enemy", + "item", + "enemy", + "do_not_click" + ] } } } diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 1cdb001be..7c3444b8c 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -102,10 +102,10 @@ Dungeon: DungeonDaily: # Dungeon names will be injected in config updater CalyxGolden: - value: Calyx_Golden_Treasures + value: Calyx_Golden_Treasures_Jarilo_VI option: [ do_not_achieve, ] CalyxCrimson: - value: Calyx_Crimson_Erudition + value: Calyx_Crimson_Destruction_Herta_StorageZone option: [ do_not_achieve, ] StagnantShadow: value: Stagnant_Shadow_Quanta @@ -192,16 +192,16 @@ Assignment: # Options in Name_x will be injected in config updater Name_1: value: Nameless_Land_Nameless_People - option: [ Nameless_Land_Nameless_People, ] + option: [ ] Name_2: value: Akashic_Records - option: [ Nameless_Land_Nameless_People, ] + option: [ ] Name_3: value: The_Invisible_Hand - option: [ Nameless_Land_Nameless_People, ] + option: [ ] Name_4: value: Nine_Billion_Names - option: [ Nameless_Land_Nameless_People, ] + option: [ ] Duration: value: 20 option: [ 4, 8, 12, 20 ] @@ -287,4 +287,6 @@ Daemon: value: true option: [ true ] option_bold: [ true, ] - + AimClicker: + value: do_not_click + option: [ item_enemy, item, enemy, do_not_click ] diff --git a/module/config/argument/default.yaml b/module/config/argument/default.yaml index 46b01f65c..c61b6d474 100644 --- a/module/config/argument/default.yaml +++ b/module/config/argument/default.yaml @@ -22,3 +22,9 @@ Assignment: Freebies: Scheduler: Enable: true + +# ==================== Weekly ==================== + +Weekly: + DungeonSupport: + Use: do_not_use diff --git a/module/config/argument/override.yaml b/module/config/argument/override.yaml index 4657d6590..bb458f39e 100644 --- a/module/config/argument/override.yaml +++ b/module/config/argument/override.yaml @@ -30,3 +30,10 @@ DataUpdate: value: true option: [ true, ] option_bold: [ true, ] + +# ==================== Weekly ==================== + +Weekly: + DungeonSupport: + Use: + option: [ always_use, do_not_use ] diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index 3182ed275..5e10c85ea 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -55,6 +55,7 @@ Weekly: Weekly: - Scheduler - Weekly + - DungeonSupport Rogue: - Scheduler - RogueWorld diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 86d644585..b3b6d3b93 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -46,20 +46,20 @@ class GeneratedConfig: CloudStorage_CloudRemainFree = {} # Group `Dungeon` - Dungeon_Name = 'Calyx_Golden_Treasures' # Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_The_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility, Stagnant_Shadow_Quanta, Stagnant_Shadow_Gust, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Blaze, Stagnant_Shadow_Spike, Stagnant_Shadow_Rime, Stagnant_Shadow_Mirage, Stagnant_Shadow_Icicle, Stagnant_Shadow_Doom, Stagnant_Shadow_Puppetry, Stagnant_Shadow_Abomination, Stagnant_Shadow_Scorch, Stagnant_Shadow_Celestial, Stagnant_Shadow_Perdition, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness - Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures' # do_not_participate, Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_The_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility - Dungeon_NameAtDoubleRelic = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_participate, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness + Dungeon_Name = 'Calyx_Golden_Treasures' # Calyx_Golden_Memories_Jarilo_VI, Calyx_Golden_Memories_The_Xianzhou_Luofu, Calyx_Golden_Memories_Penacony, Calyx_Golden_Aether_Jarilo_VI, Calyx_Golden_Aether_The_Xianzhou_Luofu, Calyx_Golden_Aether_Penacony, Calyx_Golden_Treasures_Jarilo_VI, Calyx_Golden_Treasures_The_Xianzhou_Luofu, Calyx_Golden_Treasures_Penacony, Calyx_Crimson_Destruction_Herta_StorageZone, Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape, Calyx_Crimson_Preservation_Herta_SupplyZone, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Harmony_Jarilo_RobotSettlement, Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape, Calyx_Crimson_Nihility_Jarilo_GreatMine, Calyx_Crimson_Nihility_Luofu_AlchemyCommission, Stagnant_Shadow_Spike, Stagnant_Shadow_Perdition, Stagnant_Shadow_Blaze, Stagnant_Shadow_Scorch, Stagnant_Shadow_Rime, Stagnant_Shadow_Icicle, Stagnant_Shadow_Nectar, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Doom, Stagnant_Shadow_Gust, Stagnant_Shadow_Celestial, Stagnant_Shadow_Quanta, Stagnant_Shadow_Abomination, Stagnant_Shadow_Roast, Stagnant_Shadow_Mirage, Stagnant_Shadow_Puppetry, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness, Cavern_of_Corrosion_Path_of_Dreamdive + Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures' # do_not_participate, Calyx_Golden_Memories_Jarilo_VI, Calyx_Golden_Memories_The_Xianzhou_Luofu, Calyx_Golden_Memories_Penacony, Calyx_Golden_Aether_Jarilo_VI, Calyx_Golden_Aether_The_Xianzhou_Luofu, Calyx_Golden_Aether_Penacony, Calyx_Golden_Treasures_Jarilo_VI, Calyx_Golden_Treasures_The_Xianzhou_Luofu, Calyx_Golden_Treasures_Penacony, Calyx_Crimson_Destruction_Herta_StorageZone, Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape, Calyx_Crimson_Preservation_Herta_SupplyZone, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Harmony_Jarilo_RobotSettlement, Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape, Calyx_Crimson_Nihility_Jarilo_GreatMine, Calyx_Crimson_Nihility_Luofu_AlchemyCommission + Dungeon_NameAtDoubleRelic = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_participate, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness, Cavern_of_Corrosion_Path_of_Dreamdive Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6, 7, 8, 9 # Group `DungeonDaily` - DungeonDaily_CalyxGolden = 'Calyx_Golden_Treasures' # do_not_achieve, Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures - DungeonDaily_CalyxCrimson = 'Calyx_Crimson_Erudition' # do_not_achieve, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_The_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility - DungeonDaily_StagnantShadow = 'Stagnant_Shadow_Quanta' # do_not_achieve, Stagnant_Shadow_Quanta, Stagnant_Shadow_Gust, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Blaze, Stagnant_Shadow_Spike, Stagnant_Shadow_Rime, Stagnant_Shadow_Mirage, Stagnant_Shadow_Icicle, Stagnant_Shadow_Doom, Stagnant_Shadow_Puppetry, Stagnant_Shadow_Abomination, Stagnant_Shadow_Scorch, Stagnant_Shadow_Celestial, Stagnant_Shadow_Perdition - DungeonDaily_CavernOfCorrosion = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_achieve, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness + DungeonDaily_CalyxGolden = 'Calyx_Golden_Treasures_Jarilo_VI' # do_not_achieve, Calyx_Golden_Memories_Jarilo_VI, Calyx_Golden_Memories_The_Xianzhou_Luofu, Calyx_Golden_Memories_Penacony, Calyx_Golden_Aether_Jarilo_VI, Calyx_Golden_Aether_The_Xianzhou_Luofu, Calyx_Golden_Aether_Penacony, Calyx_Golden_Treasures_Jarilo_VI, Calyx_Golden_Treasures_The_Xianzhou_Luofu, Calyx_Golden_Treasures_Penacony + DungeonDaily_CalyxCrimson = 'Calyx_Crimson_Destruction_Herta_StorageZone' # do_not_achieve, Calyx_Crimson_Destruction_Herta_StorageZone, Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape, Calyx_Crimson_Preservation_Herta_SupplyZone, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Harmony_Jarilo_RobotSettlement, Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape, Calyx_Crimson_Nihility_Jarilo_GreatMine, Calyx_Crimson_Nihility_Luofu_AlchemyCommission + DungeonDaily_StagnantShadow = 'Stagnant_Shadow_Quanta' # do_not_achieve, Stagnant_Shadow_Spike, Stagnant_Shadow_Perdition, Stagnant_Shadow_Blaze, Stagnant_Shadow_Scorch, Stagnant_Shadow_Rime, Stagnant_Shadow_Icicle, Stagnant_Shadow_Nectar, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Doom, Stagnant_Shadow_Gust, Stagnant_Shadow_Celestial, Stagnant_Shadow_Quanta, Stagnant_Shadow_Abomination, Stagnant_Shadow_Roast, Stagnant_Shadow_Mirage, Stagnant_Shadow_Puppetry + DungeonDaily_CavernOfCorrosion = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_achieve, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers, Cavern_of_Corrosion_Path_of_Darkness, Cavern_of_Corrosion_Path_of_Dreamdive # Group `DungeonSupport` DungeonSupport_Use = 'when_daily' # always_use, when_daily, do_not_use - DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Argenti, Arlan, Asta, Bailu, Blade, Bronya, Clara, DanHeng, DanHengImbibitorLunae, FuXuan, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7th, Natasha, Pela, Qingque, RuanMei, Sampo, Seele, Serval, SilverWolf, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong + DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Argenti, Arlan, Asta, Bailu, BlackSwan, Blade, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, FuXuan, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7th, Misha, Natasha, Pela, Qingque, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong # Group `DungeonStorage` DungeonStorage_TrailblazePower = {} @@ -119,10 +119,10 @@ class GeneratedConfig: BattlePassStorage_BattlePassQuestTrailblazePower = {} # Group `Assignment` - Assignment_Name_1 = 'Nameless_Land_Nameless_People' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity - Assignment_Name_2 = 'Akashic_Records' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity - Assignment_Name_3 = 'The_Invisible_Hand' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity - Assignment_Name_4 = 'Nine_Billion_Names' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity + Assignment_Name_1 = 'Nameless_Land_Nameless_People' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, A_Startling_Night_Terror, Tranquility_of_Vimala_bhumi, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity, Fragments_of_Illusory_Dreams, Scalpel_and_Screwdriver + Assignment_Name_2 = 'Akashic_Records' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, A_Startling_Night_Terror, Tranquility_of_Vimala_bhumi, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity, Fragments_of_Illusory_Dreams, Scalpel_and_Screwdriver + Assignment_Name_3 = 'The_Invisible_Hand' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, A_Startling_Night_Terror, Tranquility_of_Vimala_bhumi, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity, Fragments_of_Illusory_Dreams, Scalpel_and_Screwdriver + Assignment_Name_4 = 'Nine_Billion_Names' # Nine_Billion_Names, Destruction_of_the_Destroyer, Winter_Soldiers, Born_to_Obey, Root_Out_the_Turpitude, Fire_Lord_Inflames_Blades_of_War, A_Startling_Night_Terror, Tranquility_of_Vimala_bhumi, Nameless_Land_Nameless_People, Akashic_Records, The_Invisible_Hand, Abandoned_and_Insulted, Spring_of_Life, The_Land_of_Gold, The_Blossom_in_the_Storm, Legend_of_the_Puppet_Master, The_Wages_of_Humanity, Fragments_of_Illusory_Dreams, Scalpel_and_Screwdriver Assignment_Duration = 20 # 4, 8, 12, 20 Assignment_Event = True Assignment_Assignment = {} @@ -154,3 +154,4 @@ class GeneratedConfig: # Group `Daemon` Daemon_Enable = True # True + Daemon_AimClicker = 'do_not_click' # item_enemy, item, enemy, do_not_click diff --git a/module/config/config_updater.py b/module/config/config_updater.py index d927a948d..5aa3ce6c6 100644 --- a/module/config/config_updater.py +++ b/module/config/config_updater.py @@ -1,3 +1,4 @@ +import re import typing as t from copy import deepcopy @@ -64,35 +65,42 @@ class ConfigGenerator: option_add(keys='Emulator.PackageName.option', options=list(VALID_SERVER.keys())) # Insert dungeons from tasks.dungeon.keywords import DungeonList + calyx_golden = [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Golden_Memories] \ + + [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Golden_Aether] \ + + [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Golden_Treasures] + # calyx_crimson + from tasks.rogue.keywords import KEYWORDS_ROGUE_PATH as Path + order = [Path.Destruction, Path.Preservation, Path.The_Hunt, Path.Abundance, + Path.Erudition, Path.The_Harmony, Path.Nihility] + calyx_crimson = [] + for path in order: + calyx_crimson += [dungeon.name for dungeon in DungeonList.instances.values() + if dungeon.Calyx_Crimson_Path == path] + # stagnant_shadow + from tasks.character.keywords import CombatType + stagnant_shadow = [] + for type_ in CombatType.instances.values(): + stagnant_shadow += [dungeon.name for dungeon in DungeonList.instances.values() + if dungeon.Stagnant_Shadow_Combat_Type == type_] + cavern_of_corrosion = [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Cavern_of_Corrosion] option_add( keys='Dungeon.Name.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_daily_dungeon]) + options=calyx_golden + calyx_crimson + stagnant_shadow + cavern_of_corrosion + ) # Double events - option_add( - keys='Dungeon.NameAtDoubleCalyx.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx]) - option_add( - keys='Dungeon.NameAtDoubleRelic.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Cavern_of_Corrosion]) + option_add(keys='Dungeon.NameAtDoubleCalyx.option', options=calyx_golden + calyx_crimson) + option_add(keys='Dungeon.NameAtDoubleRelic.option', options=cavern_of_corrosion) # Dungeon daily - option_add( - keys='DungeonDaily.CalyxGolden.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Golden]) - option_add( - keys='DungeonDaily.CalyxCrimson.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Crimson]) - option_add( - keys='DungeonDaily.StagnantShadow.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Stagnant_Shadow]) - option_add( - keys='DungeonDaily.CavernOfCorrosion.option', - options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Cavern_of_Corrosion]) + option_add(keys='DungeonDaily.CalyxGolden.option', options=calyx_golden) + option_add(keys='DungeonDaily.CalyxCrimson.option', options=calyx_crimson) + option_add(keys='DungeonDaily.StagnantShadow.option', options=stagnant_shadow) + option_add(keys='DungeonDaily.CavernOfCorrosion.option', options=cavern_of_corrosion) option_add( keys='Weekly.Name.option', options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Echo_of_War]) # Insert characters from tasks.character.keywords import CharacterList - unsupported_characters = ["DrRatio"] + unsupported_characters = [] characters = [character.name for character in CharacterList.instances.values() if character.name not in unsupported_characters] option_add(keys='DungeonSupport.Character.option', options=characters) @@ -107,6 +115,11 @@ class ConfigGenerator: 'option_bold': ['achievable'], 'option_light': ['not_supported'], }) + # Insert assignments + from tasks.assignment.keywords import AssignmentEntry + assignments = [entry.name for entry in AssignmentEntry.instances.values()] + for i in range(4): + option_add(keys=f'Assignment.Name_{i + 1}.option', options=assignments) # Load for path, value in deep_iter(raw, depth=2): @@ -358,12 +371,69 @@ class ConfigGenerator: ingame_lang = gui_lang_to_ingame_lang(lang) dailies = deep_get(self.argument, keys='Dungeon.Name.option') # Dungeon names + i18n_memories = { + 'cn': '材料:角色经验({dungeon})', + 'cht': '材料:角色經驗({dungeon})', + 'jp': '素材:役割経験({dungeon}):', + 'en': 'Material: Character EXP ({dungeon})', + 'es': 'Material: EXP de personaje ({dungeon})', + } + i18n_aether = { + 'cn': '材料:武器经验({dungeon})', + 'cht': '材料:武器經驗({dungeon})', + 'jp': '素材:武器経験({dungeon}):', + 'en': 'Material: Light Cone EXP ({dungeon})', + 'es': 'Material: EXP de conos de luz ({dungeon})', + } + i18n_treasure = { + 'cn': '材料:信用点({dungeon})', + 'cht': '材料:信用點({dungeon})', + 'jp': '素材:クレジット({dungeon})', + 'en': 'Material: Credit ({dungeon})', + 'es': 'Material: Créditos ({dungeon})', + } + i18n_crimson = { + 'cn': '行迹材料:{path}({plane})', + 'cht': '行跡材料:{path}({plane})', + 'jp': '軌跡素材:{path}({plane})', + 'en': 'Trace: {path} ({plane})', + 'es': 'Rastros: {path} ({plane})', + } + i18n_relic = { + 'cn': '({dungeon})', + 'cht': '({dungeon})', + 'jp': '({dungeon})', + 'en': ' ({dungeon})', + 'es': ' ({dungeon})', + } from tasks.dungeon.keywords import DungeonList, DungeonDetailed - if lang not in ['zh-CN', 'zh-TW', 'en-US', 'es-ES']: - for dungeon in DungeonList.instances.values(): - if dungeon.name in dailies: - value = dungeon.__getattribute__(ingame_lang) - deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=value) + for dungeon in DungeonList.instances.values(): + dungeon: DungeonList = dungeon + if not dungeon.plane: + continue + dungeon_name = dungeon.__getattribute__(ingame_lang) + dungeon_name = re.sub('[「」]', '', dungeon_name) + plane = dungeon.plane.__getattribute__(ingame_lang) + plane = re.sub('[「」]', '', plane) + if dungeon.is_Calyx_Golden_Memories: + deep_set(new, keys=['Dungeon', 'Name', dungeon.name], + value=i18n_memories[ingame_lang].format(dungeon=dungeon_name)) + if dungeon.is_Calyx_Golden_Aether: + deep_set(new, keys=['Dungeon', 'Name', dungeon.name], + value=i18n_aether[ingame_lang].format(dungeon=dungeon_name)) + if dungeon.is_Calyx_Golden_Treasures: + deep_set(new, keys=['Dungeon', 'Name', dungeon.name], + value=i18n_treasure[ingame_lang].format(dungeon=dungeon_name)) + if dungeon.is_Calyx_Crimson: + path = dungeon.Calyx_Crimson_Path.__getattribute__(ingame_lang) + deep_set(new, keys=['Dungeon', 'Name', dungeon.name], + value=i18n_crimson[ingame_lang].format(path=path, plane=plane)) + if dungeon.is_Cavern_of_Corrosion: + value = deep_get(new, keys=['Dungeon', 'Name', dungeon.name], default='') + suffix = i18n_relic[ingame_lang].format(dungeon=dungeon_name) + if not value.endswith(suffix): + deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=f'{value}{suffix}') + # Stagnant shadows with character names for dungeon in DungeonDetailed.instances.values(): if dungeon.name in dailies: @@ -406,10 +476,18 @@ class ConfigGenerator: value = deep_get(new, keys=['AchievableQuest', copy_from, option]) deep_set(new, keys=['AchievableQuest', quest.name, option], value=value) + # Assignments + from tasks.assignment.keywords import AssignmentEntryDetailed + for entry in AssignmentEntryDetailed.instances.values(): + entry: AssignmentEntryDetailed + value = entry.__getattribute__(ingame_lang) + for i in range(4): + deep_set(new, keys=['Assignment', f'Name_{i + 1}', entry.name], value=value) + # Echo of War - from tasks.map.keywords import MapWorld dungeons = [d for d in DungeonList.instances.values() if d.is_Echo_of_War] - for world, dungeon in zip(MapWorld.instances.values(), dungeons): + for dungeon in dungeons: + world = dungeon.plane.world world_name = world.__getattribute__(ingame_lang) dungeon_name = dungeon.__getattribute__(ingame_lang) value = f'{dungeon_name} ({world_name})' @@ -551,20 +629,12 @@ class ConfigGenerator: update('./webapp/packages/main/public/deploy.yaml.tpl', tpl) - def insert_assignment(self): - from tasks.assignment.keywords import AssignmentEntry - assignments = [entry.name for entry in AssignmentEntry.instances.values()] - for i in range(4): - deep_set(self.argument, keys=f'Assignment.Name_{i + 1}.option', value=assignments) - deep_set(self.args, keys=f'Assignment.Assignment.Name_{i + 1}.option', value=assignments) - @timer def generate(self): _ = self.args _ = self.menu _ = self.stored # _ = self.event - self.insert_assignment() # self.insert_server() write_file(filepath_args(), self.args) write_file(filepath_args('menu'), self.menu) @@ -579,11 +649,10 @@ class ConfigGenerator: class ConfigUpdater: # source, target, (optional)convert_func redirection = [ - # ('Dungeon.Dungeon.Support', 'Dungeon.DungeonSupport.Use'), - # ('Dungeon.Dungeon.SupportCharacter', 'Dungeon.DungeonSupport.Character'), - # ('Dungeon.Dungeon.Name', 'Dungeon.Dungeon.Name', convert_daily), - # ('Dungeon.Dungeon.NameAtDoubleCalyx', 'Dungeon.Dungeon.NameAtDoubleCalyx', convert_daily), - # ('Dungeon.DungeonDaily.CalyxCrimson', 'Dungeon.DungeonDaily.CalyxCrimson', convert_daily), + ('Dungeon.Dungeon.Name', 'Dungeon.Dungeon.Name', convert_20_dungeon), + ('Dungeon.Dungeon.NameAtDoubleCalyx', 'Dungeon.Dungeon.NameAtDoubleCalyx', convert_20_dungeon), + ('Dungeon.DungeonDaily.CalyxGolden', 'Dungeon.DungeonDaily.CalyxGolden', convert_20_dungeon), + ('Dungeon.DungeonDaily.CalyxCrimson', 'Dungeon.DungeonDaily.CalyxCrimson', convert_20_dungeon), ] @cached_property diff --git a/module/config/convert.py b/module/config/convert.py index 264101d43..aadc72df4 100644 --- a/module/config/convert.py +++ b/module/config/convert.py @@ -1,4 +1,32 @@ def convert_daily(value): if value == "Calyx_Crimson_Hunt": value = "Calyx_Crimson_The_Hunt" - return value \ No newline at end of file + return value + + +def convert_20_dungeon(value): + if value == 'Calyx_Golden_Memories': + return 'Calyx_Golden_Memories_Jarilo_VI' + if value == 'Calyx_Golden_Aether': + return 'Calyx_Golden_Aether_Jarilo_VI' + if value == 'Calyx_Golden_Treasures': + return 'Calyx_Golden_Treasures_Jarilo_VI' + if value == 'Calyx_Golden_Memories': + return 'Calyx_Golden_Memories_Jarilo_VI' + + if value == 'Calyx_Crimson_Destruction': + return 'Calyx_Crimson_Destruction_Herta_StorageZone' + if value == 'Calyx_Crimson_The_Hunt': + return 'Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains' + if value == 'Calyx_Crimson_Erudition': + return 'Calyx_Crimson_Erudition_Jarilo_RivetTown' + if value == 'Calyx_Crimson_Harmony': + return 'Calyx_Crimson_Harmony_Jarilo_RobotSettlement' + if value == 'Calyx_Crimson_Nihility': + return 'Calyx_Crimson_Nihility_Jarilo_GreatMine' + if value == 'Calyx_Crimson_Preservation': + return 'Calyx_Crimson_Preservation_Herta_SupplyZone' + if value == 'Calyx_Crimson_Abundance': + return 'Calyx_Crimson_Abundance_Jarilo_BackwaterPass' + + return value diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index eeaaaea77..4d7c2ba93 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -247,30 +247,41 @@ "Name": { "name": "Dungeon Name", "help": "Default dungeon setting", - "Calyx_Golden_Memories": "Material: Character EXP (Bud of Memories)", - "Calyx_Golden_Aether": "Material: Light Cone EXP (Bud of Aether)", - "Calyx_Golden_Treasures": "Material: Credit (Bud of Treasures)", - "Calyx_Crimson_Destruction": "Trace: Destruction (Bud of Destruction)", - "Calyx_Crimson_Preservation": "Trace: Preservation (Bud of Preservation)", - "Calyx_Crimson_The_Hunt": "Trace: Hunt (Bud of Hunt)", - "Calyx_Crimson_Abundance": "Trace: Abundance (Bud of Abundance)", - "Calyx_Crimson_Erudition": "Trace: Erudition (Bud of Erudition)", - "Calyx_Crimson_Harmony": "Trace: Harmony (Bud of Harmony)", - "Calyx_Crimson_Nihility": "Trace: Nihility (Bud of Nihility)", - "Stagnant_Shadow_Quanta": "Ascension: Quantum (Silver Wolf / Seele / Qingque)", - "Stagnant_Shadow_Gust": "Ascension: Wind (Dan Heng / Bronya / Sampo)", - "Stagnant_Shadow_Fulmination": "Ascension: Lightning (Arlan / Serval / Tingyun / Bailu)", - "Stagnant_Shadow_Blaze": "Ascension: Fire (Himeko / Asta / Hook)", + "Calyx_Golden_Memories_Jarilo_VI": "Material: Character EXP (Bud of Memories (Jarilo-Ⅵ))", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: Character EXP (Bud of Memories (The Xianzhou Luofu))", + "Calyx_Golden_Memories_Penacony": "Material: Character EXP (Bud of Memories (Penacony))", + "Calyx_Golden_Aether_Jarilo_VI": "Material: Light Cone EXP (Bud of Aether (Jarilo-Ⅵ))", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: Light Cone EXP (Bud of Aether (The Xianzhou Luofu))", + "Calyx_Golden_Aether_Penacony": "Material: Light Cone EXP (Bud of Aether (Penacony))", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Credit (Bud of Treasures (Jarilo-Ⅵ))", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Credit (Bud of Treasures (The Xianzhou Luofu))", + "Calyx_Golden_Treasures_Penacony": "Material: Credit (Bud of Treasures (Penacony))", + "Calyx_Crimson_Destruction_Herta_StorageZone": "Trace: Destruction (Storage Zone)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "Trace: Destruction (Scalegorge Waterscape)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "Trace: Preservation (Supply Zone)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "Trace: The Hunt (Outlying Snow Plains)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "Trace: Abundance (Backwater Pass)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "Trace: Erudition (Rivet Town)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "Trace: The Harmony (Robot Settlement)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "Trace: The Harmony (The Reverie (Dreamscape))", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "Trace: Nihility (Great Mine)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "Trace: Nihility (Alchemy Commission)", "Stagnant_Shadow_Spike": "Ascension: Physical (Natasha / Clara / Luka / Sushang)", - "Stagnant_Shadow_Rime": "Ascension: Ice (March 7th / Herta / Gepard / Pela)", - "Stagnant_Shadow_Mirage": "Ascension: Imaginary (Welt / Luocha / Yukong)", - "Stagnant_Shadow_Icicle": "Ascension: Ice (Yanqing / Jingliu / Ruan Mei)", - "Stagnant_Shadow_Doom": "Ascension: Lightning (Kafka / Jing Yuan)", - "Stagnant_Shadow_Puppetry": "Ascension: Imaginary (Dan Heng • Imbibitor Lunae / Dr. Ratio)", - "Stagnant_Shadow_Abomination": "Ascension: Quantum (Lynx / Fu Xuan / Xueyi)", - "Stagnant_Shadow_Scorch": "Ascension: Fire (Guinaifen / Topaz & Numby)", - "Stagnant_Shadow_Celestial": "Ascension: Wind (Blade / Huohuo)", "Stagnant_Shadow_Perdition": "Ascension: Physical (Hanya / Argenti)", + "Stagnant_Shadow_Blaze": "Ascension: Fire (Himeko / Asta / Hook)", + "Stagnant_Shadow_Scorch": "Ascension: Fire (Guinaifen / Topaz & Numby)", + "Stagnant_Shadow_Rime": "Ascension: Ice (March 7th / Herta / Gepard / Pela)", + "Stagnant_Shadow_Icicle": "Ascension: Ice (Yanqing / Jingliu / Ruan Mei)", + "Stagnant_Shadow_Nectar": "Ascension: Ice (Misha)", + "Stagnant_Shadow_Fulmination": "Ascension: Lightning (Arlan / Serval / Tingyun / Bailu)", + "Stagnant_Shadow_Doom": "Ascension: Lightning (Kafka / Jing Yuan)", + "Stagnant_Shadow_Gust": "Ascension: Wind (Dan Heng / Bronya / Sampo)", + "Stagnant_Shadow_Celestial": "Ascension: Wind (Blade / Huohuo / Black Swan)", + "Stagnant_Shadow_Quanta": "Ascension: Quantum (Silver Wolf / Seele / Qingque)", + "Stagnant_Shadow_Abomination": "Ascension: Quantum (Lynx / Fu Xuan / Xueyi)", + "Stagnant_Shadow_Roast": "Ascension: Quantum (Sparkle)", + "Stagnant_Shadow_Mirage": "Ascension: Imaginary (Welt / Luocha / Yukong)", + "Stagnant_Shadow_Puppetry": "Ascension: Imaginary (Dan Heng • Imbibitor Lunae / Dr. Ratio)", "Cavern_of_Corrosion_Path_of_Gelid_Wind": "Relics: Ice Set & Wind Set (Path of Gelid Wind)", "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "Relics: Physical Set & Break Effect Set (Path of Jabbing Punch)", "Cavern_of_Corrosion_Path_of_Drifting": "Relics: Healing Set & Musketeer Set (Path of Drifting)", @@ -278,22 +289,32 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "Relics: DEF Set & Lighting Set (Path of Holy Hymn)", "Cavern_of_Corrosion_Path_of_Conflagration": "Relics: Fire Set & Imaginary Set (Path of Conflagration)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Relics: HP Set & SPD Set (Path of Elixir Seekers)", - "Cavern_of_Corrosion_Path_of_Darkness": "Relics: Pursuit Set & Dot Set (Path of Darkness)" + "Cavern_of_Corrosion_Path_of_Darkness": "Relics: Pursuit Set & Dot Set (Path of Darkness)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "Relics: Debuff Set & Break Effect Set (Path of Dreamdive)" }, "NameAtDoubleCalyx": { "name": "At Double Calyx Event, choose dungeon", "help": "Return to the default dungeon settings after double times exhausted", "do_not_participate": "Dont participate in event", - "Calyx_Golden_Memories": "Material: Character EXP (Bud of Memories)", - "Calyx_Golden_Aether": "Material: Light Cone EXP (Bud of Aether)", - "Calyx_Golden_Treasures": "Material: Credit (Bud of Treasures)", - "Calyx_Crimson_Destruction": "Trace: Destruction (Bud of Destruction)", - "Calyx_Crimson_Preservation": "Trace: Preservation (Bud of Preservation)", - "Calyx_Crimson_The_Hunt": "Trace: Hunt (Bud of Hunt)", - "Calyx_Crimson_Abundance": "Trace: Abundance (Bud of Abundance)", - "Calyx_Crimson_Erudition": "Trace: Erudition (Bud of Erudition)", - "Calyx_Crimson_Harmony": "Trace: Harmony (Bud of Harmony)", - "Calyx_Crimson_Nihility": "Trace: Nihility (Bud of Nihility)" + "Calyx_Golden_Memories_Jarilo_VI": "Material: Character EXP (Bud of Memories (Jarilo-Ⅵ))", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: Character EXP (Bud of Memories (The Xianzhou Luofu))", + "Calyx_Golden_Memories_Penacony": "Material: Character EXP (Bud of Memories (Penacony))", + "Calyx_Golden_Aether_Jarilo_VI": "Material: Light Cone EXP (Bud of Aether (Jarilo-Ⅵ))", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: Light Cone EXP (Bud of Aether (The Xianzhou Luofu))", + "Calyx_Golden_Aether_Penacony": "Material: Light Cone EXP (Bud of Aether (Penacony))", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Credit (Bud of Treasures (Jarilo-Ⅵ))", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Credit (Bud of Treasures (The Xianzhou Luofu))", + "Calyx_Golden_Treasures_Penacony": "Material: Credit (Bud of Treasures (Penacony))", + "Calyx_Crimson_Destruction_Herta_StorageZone": "Trace: Destruction (Storage Zone)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "Trace: Destruction (Scalegorge Waterscape)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "Trace: Preservation (Supply Zone)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "Trace: The Hunt (Outlying Snow Plains)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "Trace: Abundance (Backwater Pass)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "Trace: Erudition (Rivet Town)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "Trace: The Harmony (Robot Settlement)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "Trace: The Harmony (The Reverie (Dreamscape))", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "Trace: Nihility (Great Mine)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "Trace: Nihility (Alchemy Commission)" }, "NameAtDoubleRelic": { "name": "At Double Relic Event, choose dungeon", @@ -306,7 +327,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "Relics: DEF Set & Lighting Set (Path of Holy Hymn)", "Cavern_of_Corrosion_Path_of_Conflagration": "Relics: Fire Set & Imaginary Set (Path of Conflagration)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Relics: HP Set & SPD Set (Path of Elixir Seekers)", - "Cavern_of_Corrosion_Path_of_Darkness": "Relics: Pursuit Set & Dot Set (Path of Darkness)" + "Cavern_of_Corrosion_Path_of_Darkness": "Relics: Pursuit Set & Dot Set (Path of Darkness)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "Relics: Debuff Set & Break Effect Set (Path of Dreamdive)" }, "Team": { "name": "Dungeon Team", @@ -331,40 +353,51 @@ "name": "Clear Calyx Golden 1 times", "help": "", "do_not_achieve": "Don't Do This Quest", - "Calyx_Golden_Memories": "Material: Character EXP (Bud of Memories)", - "Calyx_Golden_Aether": "Material: Light Cone EXP (Bud of Aether)", - "Calyx_Golden_Treasures": "Material: Credit (Bud of Treasures)" + "Calyx_Golden_Memories_Jarilo_VI": "Material: Character EXP (Bud of Memories (Jarilo-Ⅵ))", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: Character EXP (Bud of Memories (The Xianzhou Luofu))", + "Calyx_Golden_Memories_Penacony": "Material: Character EXP (Bud of Memories (Penacony))", + "Calyx_Golden_Aether_Jarilo_VI": "Material: Light Cone EXP (Bud of Aether (Jarilo-Ⅵ))", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: Light Cone EXP (Bud of Aether (The Xianzhou Luofu))", + "Calyx_Golden_Aether_Penacony": "Material: Light Cone EXP (Bud of Aether (Penacony))", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Credit (Bud of Treasures (Jarilo-Ⅵ))", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Credit (Bud of Treasures (The Xianzhou Luofu))", + "Calyx_Golden_Treasures_Penacony": "Material: Credit (Bud of Treasures (Penacony))" }, "CalyxCrimson": { "name": "Clear Calyx Crimson 1 times", "help": "", "do_not_achieve": "Don't Do This Quest", - "Calyx_Crimson_Destruction": "Trace: Destruction (Bud of Destruction)", - "Calyx_Crimson_Preservation": "Trace: Preservation (Bud of Preservation)", - "Calyx_Crimson_The_Hunt": "Trace: Hunt (Bud of Hunt)", - "Calyx_Crimson_Abundance": "Trace: Abundance (Bud of Abundance)", - "Calyx_Crimson_Erudition": "Trace: Erudition (Bud of Erudition)", - "Calyx_Crimson_Harmony": "Trace: Harmony (Bud of Harmony)", - "Calyx_Crimson_Nihility": "Trace: Nihility (Bud of Nihility)" + "Calyx_Crimson_Destruction_Herta_StorageZone": "Trace: Destruction (Storage Zone)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "Trace: Destruction (Scalegorge Waterscape)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "Trace: Preservation (Supply Zone)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "Trace: The Hunt (Outlying Snow Plains)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "Trace: Abundance (Backwater Pass)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "Trace: Erudition (Rivet Town)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "Trace: The Harmony (Robot Settlement)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "Trace: The Harmony (The Reverie (Dreamscape))", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "Trace: Nihility (Great Mine)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "Trace: Nihility (Alchemy Commission)" }, "StagnantShadow": { "name": "Clear Stagnant Shadow 1 times", "help": "", "do_not_achieve": "Don't Do This Quest", - "Stagnant_Shadow_Quanta": "Ascension: Quantum (Silver Wolf / Seele / Qingque)", - "Stagnant_Shadow_Gust": "Ascension: Wind (Dan Heng / Bronya / Sampo)", - "Stagnant_Shadow_Fulmination": "Ascension: Lightning (Arlan / Serval / Tingyun / Bailu)", - "Stagnant_Shadow_Blaze": "Ascension: Fire (Himeko / Asta / Hook)", "Stagnant_Shadow_Spike": "Ascension: Physical (Natasha / Clara / Luka / Sushang)", - "Stagnant_Shadow_Rime": "Ascension: Ice (March 7th / Herta / Gepard / Pela)", - "Stagnant_Shadow_Mirage": "Ascension: Imaginary (Welt / Luocha / Yukong)", - "Stagnant_Shadow_Icicle": "Ascension: Ice (Yanqing / Jingliu / Ruan Mei)", - "Stagnant_Shadow_Doom": "Ascension: Lightning (Kafka / Jing Yuan)", - "Stagnant_Shadow_Puppetry": "Ascension: Imaginary (Dan Heng • Imbibitor Lunae / Dr. Ratio)", - "Stagnant_Shadow_Abomination": "Ascension: Quantum (Lynx / Fu Xuan / Xueyi)", + "Stagnant_Shadow_Perdition": "Ascension: Physical (Hanya / Argenti)", + "Stagnant_Shadow_Blaze": "Ascension: Fire (Himeko / Asta / Hook)", "Stagnant_Shadow_Scorch": "Ascension: Fire (Guinaifen / Topaz & Numby)", - "Stagnant_Shadow_Celestial": "Ascension: Wind (Blade / Huohuo)", - "Stagnant_Shadow_Perdition": "Ascension: Physical (Hanya / Argenti)" + "Stagnant_Shadow_Rime": "Ascension: Ice (March 7th / Herta / Gepard / Pela)", + "Stagnant_Shadow_Icicle": "Ascension: Ice (Yanqing / Jingliu / Ruan Mei)", + "Stagnant_Shadow_Nectar": "Ascension: Ice (Misha)", + "Stagnant_Shadow_Fulmination": "Ascension: Lightning (Arlan / Serval / Tingyun / Bailu)", + "Stagnant_Shadow_Doom": "Ascension: Lightning (Kafka / Jing Yuan)", + "Stagnant_Shadow_Gust": "Ascension: Wind (Dan Heng / Bronya / Sampo)", + "Stagnant_Shadow_Celestial": "Ascension: Wind (Blade / Huohuo / Black Swan)", + "Stagnant_Shadow_Quanta": "Ascension: Quantum (Silver Wolf / Seele / Qingque)", + "Stagnant_Shadow_Abomination": "Ascension: Quantum (Lynx / Fu Xuan / Xueyi)", + "Stagnant_Shadow_Roast": "Ascension: Quantum (Sparkle)", + "Stagnant_Shadow_Mirage": "Ascension: Imaginary (Welt / Luocha / Yukong)", + "Stagnant_Shadow_Puppetry": "Ascension: Imaginary (Dan Heng • Imbibitor Lunae / Dr. Ratio)" }, "CavernOfCorrosion": { "name": "Clear Cavern of Corrosion 1 times", @@ -377,7 +410,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "Relics: DEF Set & Lighting Set (Path of Holy Hymn)", "Cavern_of_Corrosion_Path_of_Conflagration": "Relics: Fire Set & Imaginary Set (Path of Conflagration)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Relics: HP Set & SPD Set (Path of Elixir Seekers)", - "Cavern_of_Corrosion_Path_of_Darkness": "Relics: Pursuit Set & Dot Set (Path of Darkness)" + "Cavern_of_Corrosion_Path_of_Darkness": "Relics: Pursuit Set & Dot Set (Path of Darkness)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "Relics: Debuff Set & Break Effect Set (Path of Dreamdive)" } }, "DungeonSupport": { @@ -394,17 +428,19 @@ }, "Character": { "name": "Support Character", - "help": "Select a friend support character, if not found, select the default (first) role", + "help": "Select a friend support character, if not found, select the default (first) role\nSupport character should not be the same as the character in the team, recommended to prioritize friends.", "FirstCharacter": "First Character", "Argenti": "Argenti", "Arlan": "Arlan", "Asta": "Asta", "Bailu": "Bailu", + "BlackSwan": "Black Swan", "Blade": "Blade", "Bronya": "Bronya", "Clara": "Clara", "DanHeng": "Dan Heng", "DanHengImbibitorLunae": "Dan Heng • Imbibitor Lunae", + "DrRatio": "Dr. Ratio", "FuXuan": "Fu Xuan", "Gepard": "Gepard", "Guinaifen": "Guinaifen", @@ -420,6 +456,7 @@ "Luocha": "Luocha", "Lynx": "Lynx", "March7th": "March 7th", + "Misha": "Misha", "Natasha": "Natasha", "Pela": "Pela", "Qingque": "Qingque", @@ -428,6 +465,7 @@ "Seele": "Seele", "Serval": "Serval", "SilverWolf": "Silver Wolf", + "Sparkle": "Sparkle", "Sushang": "Sushang", "Tingyun": "Tingyun", "TopazNumby": "Topaz & Numby", @@ -760,15 +798,19 @@ "Born_to_Obey": "Ancient Part (Born to Obey)", "Root_Out_the_Turpitude": "Immortal Scionette (Root Out the Turpitude)", "Fire_Lord_Inflames_Blades_of_War": "Artifex's Module (Fire Lord Inflames Blades of War)", + "A_Startling_Night_Terror": "Dream Collection Component (A Startling Night Terror)", + "Tranquility_of_Vimala_bhumi": "Tatters of Thought (Tranquility of Vimala-bhumi)", "Nameless_Land_Nameless_People": "Character EXP Material (Nameless Land, Nameless People)", "Akashic_Records": "Light Cone EXP Material (Akashic Records)", "The_Invisible_Hand": "Credit (The Invisible Hand)", "Abandoned_and_Insulted": "Phlogiston & Metal (Abandoned and Insulted)", - "Spring_of_Life": "Virtual Particle & Solid Water (Spring of Life)", - "The_Land_of_Gold": "Protein Rice & Basic Ingredients (The Land of Gold)", + "Spring_of_Life": "Solid Water & Virtual Particle (Spring of Life)", + "The_Land_of_Gold": "Basic Ingredients & Protein Rice (The Land of Gold)", "The_Blossom_in_the_Storm": "Gaseous Liquid & Seed (The Blossom in the Storm)", - "Legend_of_the_Puppet_Master": "Jade Abacus Unit & Discarded Ingenium Parts (Legend of the Puppet Master)", - "The_Wages_of_Humanity": "Extract of Medicinal Herbs & Human-Height Auspicious Crops (The Wages of Humanity)" + "Legend_of_the_Puppet_Master": "Discarded Ingenium Parts & Jade Abacus Unit (Legend of the Puppet Master)", + "The_Wages_of_Humanity": "Human-Height Auspicious Crops & Extract of Medicinal Herbs (The Wages of Humanity)", + "Fragments_of_Illusory_Dreams": "Tranquility & Broken Dreams (Fragments of Illusory Dreams)", + "Scalpel_and_Screwdriver": "Rusty Gear & Old Molar (Scalpel and Screwdriver)" }, "Name_2": { "name": "Assignment 2 Preference", @@ -779,15 +821,19 @@ "Born_to_Obey": "Ancient Part (Born to Obey)", "Root_Out_the_Turpitude": "Immortal Scionette (Root Out the Turpitude)", "Fire_Lord_Inflames_Blades_of_War": "Artifex's Module (Fire Lord Inflames Blades of War)", + "A_Startling_Night_Terror": "Dream Collection Component (A Startling Night Terror)", + "Tranquility_of_Vimala_bhumi": "Tatters of Thought (Tranquility of Vimala-bhumi)", "Nameless_Land_Nameless_People": "Character EXP Material (Nameless Land, Nameless People)", "Akashic_Records": "Light Cone EXP Material (Akashic Records)", "The_Invisible_Hand": "Credit (The Invisible Hand)", "Abandoned_and_Insulted": "Phlogiston & Metal (Abandoned and Insulted)", - "Spring_of_Life": "Virtual Particle & Solid Water (Spring of Life)", - "The_Land_of_Gold": "Protein Rice & Basic Ingredients (The Land of Gold)", + "Spring_of_Life": "Solid Water & Virtual Particle (Spring of Life)", + "The_Land_of_Gold": "Basic Ingredients & Protein Rice (The Land of Gold)", "The_Blossom_in_the_Storm": "Gaseous Liquid & Seed (The Blossom in the Storm)", - "Legend_of_the_Puppet_Master": "Jade Abacus Unit & Discarded Ingenium Parts (Legend of the Puppet Master)", - "The_Wages_of_Humanity": "Extract of Medicinal Herbs & Human-Height Auspicious Crops (The Wages of Humanity)" + "Legend_of_the_Puppet_Master": "Discarded Ingenium Parts & Jade Abacus Unit (Legend of the Puppet Master)", + "The_Wages_of_Humanity": "Human-Height Auspicious Crops & Extract of Medicinal Herbs (The Wages of Humanity)", + "Fragments_of_Illusory_Dreams": "Tranquility & Broken Dreams (Fragments of Illusory Dreams)", + "Scalpel_and_Screwdriver": "Rusty Gear & Old Molar (Scalpel and Screwdriver)" }, "Name_3": { "name": "Assignment 3 Preference", @@ -798,15 +844,19 @@ "Born_to_Obey": "Ancient Part (Born to Obey)", "Root_Out_the_Turpitude": "Immortal Scionette (Root Out the Turpitude)", "Fire_Lord_Inflames_Blades_of_War": "Artifex's Module (Fire Lord Inflames Blades of War)", + "A_Startling_Night_Terror": "Dream Collection Component (A Startling Night Terror)", + "Tranquility_of_Vimala_bhumi": "Tatters of Thought (Tranquility of Vimala-bhumi)", "Nameless_Land_Nameless_People": "Character EXP Material (Nameless Land, Nameless People)", "Akashic_Records": "Light Cone EXP Material (Akashic Records)", "The_Invisible_Hand": "Credit (The Invisible Hand)", "Abandoned_and_Insulted": "Phlogiston & Metal (Abandoned and Insulted)", - "Spring_of_Life": "Virtual Particle & Solid Water (Spring of Life)", - "The_Land_of_Gold": "Protein Rice & Basic Ingredients (The Land of Gold)", + "Spring_of_Life": "Solid Water & Virtual Particle (Spring of Life)", + "The_Land_of_Gold": "Basic Ingredients & Protein Rice (The Land of Gold)", "The_Blossom_in_the_Storm": "Gaseous Liquid & Seed (The Blossom in the Storm)", - "Legend_of_the_Puppet_Master": "Jade Abacus Unit & Discarded Ingenium Parts (Legend of the Puppet Master)", - "The_Wages_of_Humanity": "Extract of Medicinal Herbs & Human-Height Auspicious Crops (The Wages of Humanity)" + "Legend_of_the_Puppet_Master": "Discarded Ingenium Parts & Jade Abacus Unit (Legend of the Puppet Master)", + "The_Wages_of_Humanity": "Human-Height Auspicious Crops & Extract of Medicinal Herbs (The Wages of Humanity)", + "Fragments_of_Illusory_Dreams": "Tranquility & Broken Dreams (Fragments of Illusory Dreams)", + "Scalpel_and_Screwdriver": "Rusty Gear & Old Molar (Scalpel and Screwdriver)" }, "Name_4": { "name": "Assignment 4 Preference", @@ -817,15 +867,19 @@ "Born_to_Obey": "Ancient Part (Born to Obey)", "Root_Out_the_Turpitude": "Immortal Scionette (Root Out the Turpitude)", "Fire_Lord_Inflames_Blades_of_War": "Artifex's Module (Fire Lord Inflames Blades of War)", + "A_Startling_Night_Terror": "Dream Collection Component (A Startling Night Terror)", + "Tranquility_of_Vimala_bhumi": "Tatters of Thought (Tranquility of Vimala-bhumi)", "Nameless_Land_Nameless_People": "Character EXP Material (Nameless Land, Nameless People)", "Akashic_Records": "Light Cone EXP Material (Akashic Records)", "The_Invisible_Hand": "Credit (The Invisible Hand)", "Abandoned_and_Insulted": "Phlogiston & Metal (Abandoned and Insulted)", - "Spring_of_Life": "Virtual Particle & Solid Water (Spring of Life)", - "The_Land_of_Gold": "Protein Rice & Basic Ingredients (The Land of Gold)", + "Spring_of_Life": "Solid Water & Virtual Particle (Spring of Life)", + "The_Land_of_Gold": "Basic Ingredients & Protein Rice (The Land of Gold)", "The_Blossom_in_the_Storm": "Gaseous Liquid & Seed (The Blossom in the Storm)", - "Legend_of_the_Puppet_Master": "Jade Abacus Unit & Discarded Ingenium Parts (Legend of the Puppet Master)", - "The_Wages_of_Humanity": "Extract of Medicinal Herbs & Human-Height Auspicious Crops (The Wages of Humanity)" + "Legend_of_the_Puppet_Master": "Discarded Ingenium Parts & Jade Abacus Unit (Legend of the Puppet Master)", + "The_Wages_of_Humanity": "Human-Height Auspicious Crops & Extract of Medicinal Herbs (The Wages of Humanity)", + "Fragments_of_Illusory_Dreams": "Tranquility & Broken Dreams (Fragments of Illusory Dreams)", + "Scalpel_and_Screwdriver": "Rusty Gear & Old Molar (Scalpel and Screwdriver)" }, "Duration": { "name": "Dispatch Duration", @@ -974,6 +1028,14 @@ "name": "Dialogue Clicker", "help": "Monitor game, automatically click dialogue, phone chatting, and blessing in simulated universe (follow the simulated universe task settings)", "True": "Enabled" + }, + "AimClicker": { + "name": "Click Aimed Items and Enemies", + "help": "", + "item_enemy": "Click items and enemies", + "item": "Click items only", + "enemy": "Click enemies only", + "do_not_click": "Don't click" } }, "Gui": { diff --git a/module/config/i18n/es-ES.json b/module/config/i18n/es-ES.json index a962b8952..db34fd6b2 100644 --- a/module/config/i18n/es-ES.json +++ b/module/config/i18n/es-ES.json @@ -247,53 +247,74 @@ "Name": { "name": "Nombre de la Mazmorra", "help": "Ajustes predeterminados de las mazmorras", - "Calyx_Golden_Memories": "Material: EXP de personaje (Flor de los recuerdos)", - "Calyx_Golden_Aether": "Material: EXP de conos de luz (Flor de éter)", - "Calyx_Golden_Treasures": "Material: Créditos (Flor de tesoros)", - "Calyx_Crimson_Destruction": "Rastros: Destrucción (Flor de la Destrucción)", - "Calyx_Crimson_Preservation": "Rastros: Conservación (Flor de la Conservación)", - "Calyx_Crimson_The_Hunt": "Rastros: Cacería (Flor de la Cacería)", - "Calyx_Crimson_Abundance": "Rastros: Abundancia (Flor de la Abundancia)", - "Calyx_Crimson_Erudition": "Rastros: Erudición (Flor de la Erudición)", - "Calyx_Crimson_Harmony": "Rastros: Armonía (Flor de la Armonía)", - "Calyx_Crimson_Nihility": "Rastros: Nihilidad (Flor de la Nihilidad)", - "Stagnant_Shadow_Quanta": "Ascension: Cuántico (Silver Wolf / Seele / Qingque)", - "Stagnant_Shadow_Gust": "Ascension: Viento (Dan Heng / Bronya / Sampo)", - "Stagnant_Shadow_Fulmination": "Ascension: Rayo (Arlan / Serval / Tingyun / Bailu)", - "Stagnant_Shadow_Blaze": "Ascension: Fuego (Himeko / Asta / Hook)", + "Calyx_Golden_Memories_Jarilo_VI": "Material: EXP de personaje (Flor de los recuerdos (Jarilo-Ⅵ))", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: EXP de personaje (Flor de los recuerdos (El Luofu de Xianzhou))", + "Calyx_Golden_Memories_Penacony": "Material: EXP de personaje (Flor de los recuerdos (Colonipenal))", + "Calyx_Golden_Aether_Jarilo_VI": "Material: EXP de conos de luz (Flor de éter (Jarilo-Ⅵ))", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: EXP de conos de luz (Flor de éter (El Luofu de Xianzhou))", + "Calyx_Golden_Aether_Penacony": "Material: EXP de conos de luz (Flor de éter (Colonipenal))", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Créditos (Flor de tesoros (Jarilo-Ⅵ))", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Créditos (Flor de tesoros (El Luofu de Xianzhou))", + "Calyx_Golden_Treasures_Penacony": "Material: Créditos (Flor de tesoros (Colonipenal))", + "Calyx_Crimson_Destruction_Herta_StorageZone": "Rastros: Destrucción (Zona de almacenamiento)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "Rastros: Destrucción (Desfiladero de Escamas)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "Rastros: Conservación (Zona de suministros)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "Rastros: Cacería (Llanuras nevadas de las afueras)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "Rastros: Abundancia (Paso del Remanso)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "Rastros: Erudición (Villarremache)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "Rastros: Armonía (Asentamiento robot)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "Rastros: Armonía (Hotel Fantasía (paisaje onírico))", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "Rastros: Nihilidad (Mina principal)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "Rastros: Nihilidad (Comisión de Alquimia)", "Stagnant_Shadow_Spike": "Ascension: Físico (Natasha / Clara / Luka / Sushang)", - "Stagnant_Shadow_Rime": "Ascension: Hielo (Siete de Marzo / Herta / Gepard / Pela)", - "Stagnant_Shadow_Mirage": "Ascension: Imaginario (Welt / Luocha / Yukong)", - "Stagnant_Shadow_Icicle": "Ascension: Hielo (Yanqing / Jingliu / Ruan Mei)", - "Stagnant_Shadow_Doom": "Ascension: Rayo (Kafka / Jing Yuan)", - "Stagnant_Shadow_Puppetry": "Ascension: Imaginario (Dan Heng - Imbibitor Lunae / Dr. Ratio)", - "Stagnant_Shadow_Abomination": "Ascension: Cuántico (Lynx / Fu Xuan / Xueyi)", - "Stagnant_Shadow_Scorch": "Ascension: Fuego (Guinaifen / Topaz y Conti)", - "Stagnant_Shadow_Celestial": "Ascension: Viento (Blade / Huohuo)", "Stagnant_Shadow_Perdition": "Ascension: Físico (Hanya / Argenti)", + "Stagnant_Shadow_Blaze": "Ascension: Fuego (Himeko / Asta / Hook)", + "Stagnant_Shadow_Scorch": "Ascension: Fuego (Guinaifen / Topaz y Conti)", + "Stagnant_Shadow_Rime": "Ascension: Hielo (Siete de Marzo / Herta / Gepard / Pela)", + "Stagnant_Shadow_Icicle": "Ascension: Hielo (Yanqing / Jingliu / Ruan Mei)", + "Stagnant_Shadow_Nectar": "Ascension: Hielo (Misha)", + "Stagnant_Shadow_Fulmination": "Ascension: Rayo (Arlan / Serval / Tingyun / Bailu)", + "Stagnant_Shadow_Doom": "Ascension: Rayo (Kafka / Jing Yuan)", + "Stagnant_Shadow_Gust": "Ascension: Viento (Dan Heng / Bronya / Sampo)", + "Stagnant_Shadow_Celestial": "Ascension: Viento (Blade / Huohuo / Cisne Negro)", + "Stagnant_Shadow_Quanta": "Ascension: Cuántico (Silver Wolf / Seele / Qingque)", + "Stagnant_Shadow_Abomination": "Ascension: Cuántico (Lynx / Fu Xuan / Xueyi)", + "Stagnant_Shadow_Roast": "Ascension: Cuántico (Sparkle)", + "Stagnant_Shadow_Mirage": "Ascension: Imaginario (Welt / Luocha / Yukong)", + "Stagnant_Shadow_Puppetry": "Ascension: Imaginario (Dan Heng - Imbibitor Lunae / Dr. Ratio)", "Cavern_of_Corrosion_Path_of_Gelid_Wind": "Artefactos: Hielo y Viento (Senda del viento gélido)", "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "Artefactos: Físico y Efecto de Ruptura (Senda de los puños rápidos)", "Cavern_of_Corrosion_Path_of_Drifting": "Artefactos: Curación y Pistolera de la espiga silvestre (Senda de la deriva)", - "Cavern_of_Corrosion_Path_of_Providence": "Artefactos: Guardia de la nieve y Cuántico (Senda de al providencia)", + "Cavern_of_Corrosion_Path_of_Providence": "Artefactos: Guardia de la nieve y Cuántico (Senda de al providencia) (Senda de la providencia)", "Cavern_of_Corrosion_Path_of_Holy_Hymn": "Artefactos: Defensa y Trueno (Senda del himno sagrado)", "Cavern_of_Corrosion_Path_of_Conflagration": "Artefactos: Fuego e Imaginario (Senda de la conflagración)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Artefactos: HP y SPD (Senda de los elixires)", - "Cavern_of_Corrosion_Path_of_Darkness": "Artefactos: Persecución y Dot (Senda de la oscuridad)" + "Cavern_of_Corrosion_Path_of_Darkness": "Artefactos: Persecución y Dot (Senda de la oscuridad)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "Artefactos: Debuff y Efecto de Ruptura (Senda de los sueños)" }, "NameAtDoubleCalyx": { "name": "En los eventos de x2 de Cáliz", "help": "Se volverán a los ajustes predeterminados una vez se acaben los intentos del evento", "do_not_participate": "No participar en el evento", - "Calyx_Golden_Memories": "Material: EXP de personaje (Flor de los recuerdos)", - "Calyx_Golden_Aether": "Material: EXP de conos de luz (Flor de éter)", - "Calyx_Golden_Treasures": "Material: Créditos (Flor de tesoros)", - "Calyx_Crimson_Destruction": "Rastros: Destrucción (Flor de la Destrucción)", - "Calyx_Crimson_Preservation": "Rastros: Conservación (Flor de la Conservación)", - "Calyx_Crimson_The_Hunt": "Rastros: Cacería (Flor de la Cacería)", - "Calyx_Crimson_Abundance": "Rastros: Abundancia (Flor de la Abundancia)", - "Calyx_Crimson_Erudition": "Rastros: Erudición (Flor de la Erudición)", - "Calyx_Crimson_Harmony": "Rastros: Armonía (Flor de la Armonía)", - "Calyx_Crimson_Nihility": "Rastros: Nihilidad (Flor de la Nihilidad)" + "Calyx_Golden_Memories_Jarilo_VI": "Material: EXP de personaje (Flor de los recuerdos (Jarilo-Ⅵ))", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: EXP de personaje (Flor de los recuerdos (El Luofu de Xianzhou))", + "Calyx_Golden_Memories_Penacony": "Material: EXP de personaje (Flor de los recuerdos (Colonipenal))", + "Calyx_Golden_Aether_Jarilo_VI": "Material: EXP de conos de luz (Flor de éter (Jarilo-Ⅵ))", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: EXP de conos de luz (Flor de éter (El Luofu de Xianzhou))", + "Calyx_Golden_Aether_Penacony": "Material: EXP de conos de luz (Flor de éter (Colonipenal))", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Créditos (Flor de tesoros (Jarilo-Ⅵ))", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Créditos (Flor de tesoros (El Luofu de Xianzhou))", + "Calyx_Golden_Treasures_Penacony": "Material: Créditos (Flor de tesoros (Colonipenal))", + "Calyx_Crimson_Destruction_Herta_StorageZone": "Rastros: Destrucción (Zona de almacenamiento)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "Rastros: Destrucción (Desfiladero de Escamas)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "Rastros: Conservación (Zona de suministros)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "Rastros: Cacería (Llanuras nevadas de las afueras)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "Rastros: Abundancia (Paso del Remanso)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "Rastros: Erudición (Villarremache)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "Rastros: Armonía (Asentamiento robot)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "Rastros: Armonía (Hotel Fantasía (paisaje onírico))", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "Rastros: Nihilidad (Mina principal)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "Rastros: Nihilidad (Comisión de Alquimia)" }, "NameAtDoubleRelic": { "name": "En los eventos de x2 de Caverna de la corrosión", @@ -302,11 +323,12 @@ "Cavern_of_Corrosion_Path_of_Gelid_Wind": "Artefactos: Hielo y Viento (Senda del viento gélido)", "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "Artefactos: Físico y Efecto de Ruptura (Senda de los puños rápidos)", "Cavern_of_Corrosion_Path_of_Drifting": "Artefactos: Curación y Pistolera de la espiga silvestre (Senda de la deriva)", - "Cavern_of_Corrosion_Path_of_Providence": "Artefactos: Guardia de la nieve y Cuántico (Senda de al providencia)", + "Cavern_of_Corrosion_Path_of_Providence": "Artefactos: Guardia de la nieve y Cuántico (Senda de al providencia) (Senda de la providencia)", "Cavern_of_Corrosion_Path_of_Holy_Hymn": "Artefactos: Defensa y Trueno (Senda del himno sagrado)", "Cavern_of_Corrosion_Path_of_Conflagration": "Artefactos: Fuego e Imaginario (Senda de la conflagración)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Artefactos: HP y SPD (Senda de los elixires)", - "Cavern_of_Corrosion_Path_of_Darkness": "Artefactos: Persecución y Dot (Senda de la oscuridad)" + "Cavern_of_Corrosion_Path_of_Darkness": "Artefactos: Persecución y Dot (Senda de la oscuridad)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "Artefactos: Debuff y Efecto de Ruptura (Senda de los sueños)" }, "Team": { "name": "Equipo de mazmorra", @@ -331,40 +353,51 @@ "name": "Completar Cáliz (oro) 1 vez", "help": "", "do_not_achieve": "No hacer esta misión", - "Calyx_Golden_Memories": "Material: EXP de personaje (Flor de los recuerdos)", - "Calyx_Golden_Aether": "Material: EXP de conos de luz (Flor de éter)", - "Calyx_Golden_Treasures": "Material: Créditos (Flor de tesoros)" + "Calyx_Golden_Memories_Jarilo_VI": "Material: EXP de personaje (Flor de los recuerdos (Jarilo-Ⅵ))", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: EXP de personaje (Flor de los recuerdos (El Luofu de Xianzhou))", + "Calyx_Golden_Memories_Penacony": "Material: EXP de personaje (Flor de los recuerdos (Colonipenal))", + "Calyx_Golden_Aether_Jarilo_VI": "Material: EXP de conos de luz (Flor de éter (Jarilo-Ⅵ))", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: EXP de conos de luz (Flor de éter (El Luofu de Xianzhou))", + "Calyx_Golden_Aether_Penacony": "Material: EXP de conos de luz (Flor de éter (Colonipenal))", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Créditos (Flor de tesoros (Jarilo-Ⅵ))", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Créditos (Flor de tesoros (El Luofu de Xianzhou))", + "Calyx_Golden_Treasures_Penacony": "Material: Créditos (Flor de tesoros (Colonipenal))" }, "CalyxCrimson": { "name": "Completar Cáliz (carmesí) 1 vez", "help": "", "do_not_achieve": "No hacer esta misión", - "Calyx_Crimson_Destruction": "Rastros: Destrucción (Flor de la Destrucción)", - "Calyx_Crimson_Preservation": "Rastros: Conservación (Flor de la Conservación)", - "Calyx_Crimson_The_Hunt": "Rastros: Cacería (Flor de la Cacería)", - "Calyx_Crimson_Abundance": "Rastros: Abundancia (Flor de la Abundancia)", - "Calyx_Crimson_Erudition": "Rastros: Erudición (Flor de la Erudición)", - "Calyx_Crimson_Harmony": "Rastros: Armonía (Flor de la Armonía)", - "Calyx_Crimson_Nihility": "Rastros: Nihilidad (Flor de la Nihilidad)" + "Calyx_Crimson_Destruction_Herta_StorageZone": "Rastros: Destrucción (Zona de almacenamiento)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "Rastros: Destrucción (Desfiladero de Escamas)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "Rastros: Conservación (Zona de suministros)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "Rastros: Cacería (Llanuras nevadas de las afueras)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "Rastros: Abundancia (Paso del Remanso)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "Rastros: Erudición (Villarremache)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "Rastros: Armonía (Asentamiento robot)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "Rastros: Armonía (Hotel Fantasía (paisaje onírico))", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "Rastros: Nihilidad (Mina principal)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "Rastros: Nihilidad (Comisión de Alquimia)" }, "StagnantShadow": { "name": "Completar Sombra paralizada 1 vez", "help": "", "do_not_achieve": "No hacer esta misión", - "Stagnant_Shadow_Quanta": "Ascension: Cuántico (Silver Wolf / Seele / Qingque)", - "Stagnant_Shadow_Gust": "Ascension: Viento (Dan Heng / Bronya / Sampo)", - "Stagnant_Shadow_Fulmination": "Ascension: Rayo (Arlan / Serval / Tingyun / Bailu)", - "Stagnant_Shadow_Blaze": "Ascension: Fuego (Himeko / Asta / Hook)", "Stagnant_Shadow_Spike": "Ascension: Físico (Natasha / Clara / Luka / Sushang)", - "Stagnant_Shadow_Rime": "Ascension: Hielo (Siete de Marzo / Herta / Gepard / Pela)", - "Stagnant_Shadow_Mirage": "Ascension: Imaginario (Welt / Luocha / Yukong)", - "Stagnant_Shadow_Icicle": "Ascension: Hielo (Yanqing / Jingliu / Ruan Mei)", - "Stagnant_Shadow_Doom": "Ascension: Rayo (Kafka / Jing Yuan)", - "Stagnant_Shadow_Puppetry": "Ascension: Imaginario (Dan Heng - Imbibitor Lunae / Dr. Ratio)", - "Stagnant_Shadow_Abomination": "Ascension: Cuántico (Lynx / Fu Xuan / Xueyi)", + "Stagnant_Shadow_Perdition": "Ascension: Físico (Hanya / Argenti)", + "Stagnant_Shadow_Blaze": "Ascension: Fuego (Himeko / Asta / Hook)", "Stagnant_Shadow_Scorch": "Ascension: Fuego (Guinaifen / Topaz y Conti)", - "Stagnant_Shadow_Celestial": "Ascension: Viento (Blade / Huohuo)", - "Stagnant_Shadow_Perdition": "Ascension: Físico (Hanya / Argenti)" + "Stagnant_Shadow_Rime": "Ascension: Hielo (Siete de Marzo / Herta / Gepard / Pela)", + "Stagnant_Shadow_Icicle": "Ascension: Hielo (Yanqing / Jingliu / Ruan Mei)", + "Stagnant_Shadow_Nectar": "Ascension: Hielo (Misha)", + "Stagnant_Shadow_Fulmination": "Ascension: Rayo (Arlan / Serval / Tingyun / Bailu)", + "Stagnant_Shadow_Doom": "Ascension: Rayo (Kafka / Jing Yuan)", + "Stagnant_Shadow_Gust": "Ascension: Viento (Dan Heng / Bronya / Sampo)", + "Stagnant_Shadow_Celestial": "Ascension: Viento (Blade / Huohuo / Cisne Negro)", + "Stagnant_Shadow_Quanta": "Ascension: Cuántico (Silver Wolf / Seele / Qingque)", + "Stagnant_Shadow_Abomination": "Ascension: Cuántico (Lynx / Fu Xuan / Xueyi)", + "Stagnant_Shadow_Roast": "Ascension: Cuántico (Sparkle)", + "Stagnant_Shadow_Mirage": "Ascension: Imaginario (Welt / Luocha / Yukong)", + "Stagnant_Shadow_Puppetry": "Ascension: Imaginario (Dan Heng - Imbibitor Lunae / Dr. Ratio)" }, "CavernOfCorrosion": { "name": "Completar Caverna de la corrosión 1 vez", @@ -373,11 +406,12 @@ "Cavern_of_Corrosion_Path_of_Gelid_Wind": "Artefactos: Hielo y Viento (Senda del viento gélido)", "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "Artefactos: Físico y Efecto de Ruptura (Senda de los puños rápidos)", "Cavern_of_Corrosion_Path_of_Drifting": "Artefactos: Curación y Pistolera de la espiga silvestre (Senda de la deriva)", - "Cavern_of_Corrosion_Path_of_Providence": "Artefactos: Guardia de la nieve y Cuántico (Senda de al providencia)", + "Cavern_of_Corrosion_Path_of_Providence": "Artefactos: Guardia de la nieve y Cuántico (Senda de al providencia) (Senda de la providencia)", "Cavern_of_Corrosion_Path_of_Holy_Hymn": "Artefactos: Defensa y Trueno (Senda del himno sagrado)", "Cavern_of_Corrosion_Path_of_Conflagration": "Artefactos: Fuego e Imaginario (Senda de la conflagración)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Artefactos: HP y SPD (Senda de los elixires)", - "Cavern_of_Corrosion_Path_of_Darkness": "Artefactos: Persecución y Dot (Senda de la oscuridad)" + "Cavern_of_Corrosion_Path_of_Darkness": "Artefactos: Persecución y Dot (Senda de la oscuridad)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "Artefactos: Debuff y Efecto de Ruptura (Senda de los sueños)" } }, "DungeonSupport": { @@ -394,17 +428,19 @@ }, "Character": { "name": "Personaje de apoyo", - "help": "Selecciona qué personaje de apoyo de un amigo se usará. Si no se encuentra, se seleccionará al predeterminado.", + "help": "Selecciona qué personaje de apoyo de un amigo se usará. Si no se encuentra, se seleccionará al predeterminado.\nEl personaje de apoyo no debe ser el mismo que el personaje del equipo, se recomienda priorizar a los amigos.", "FirstCharacter": "Primer personaje", "Argenti": "Argenti", "Arlan": "Arlan", "Asta": "Asta", "Bailu": "Bailu", + "BlackSwan": "Cisne Negro", "Blade": "Blade", "Bronya": "Bronya", "Clara": "Clara", "DanHeng": "Dan Heng", "DanHengImbibitorLunae": "Dan Heng - Imbibitor Lunae", + "DrRatio": "Dr. Ratio", "FuXuan": "Fu Xuan", "Gepard": "Gepard", "Guinaifen": "Guinaifen", @@ -420,6 +456,7 @@ "Luocha": "Luocha", "Lynx": "Lynx", "March7th": "Siete de Marzo", + "Misha": "Misha", "Natasha": "Natasha", "Pela": "Pela", "Qingque": "Qingque", @@ -428,6 +465,7 @@ "Seele": "Seele", "Serval": "Serval", "SilverWolf": "Silver Wolf", + "Sparkle": "Sparkle", "Sushang": "Sushang", "Tingyun": "Tingyun", "TopazNumby": "Topaz y Conti", @@ -755,77 +793,93 @@ "name": "Preferencia de Encargo 1", "help": "", "Nine_Billion_Names": "Núcleo apagado (Nueve mil millones de nombres)", - "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucci´pon del destructor)", + "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucción del destructor)", "Winter_Soldiers": "Pin del guardia (Los guerreros del invierno)", "Born_to_Obey": "Componente antiguo (Creados para obedecer)", "Root_Out_the_Turpitude": "Brote verde inmortal (La raíz del mal)", "Fire_Lord_Inflames_Blades_of_War": "Componente artificial mecánico (Prendan los fuelles, fundan las armas)", + "A_Startling_Night_Terror": "Componente del acumulador de sueños (Pesadilla aterradora)", + "Tranquility_of_Vimala_bhumi": "Jirones de pensamientos (Limpieza y purificación)", "Nameless_Land_Nameless_People": "Material de EXP de personaje (Lugar anónimo, personas anónimas)", - "Akashic_Records": "Material de EXP de cono de luz (Los Registros de Akasha)", - "The_Invisible_Hand": "Créditos (La mano invisible)", - "Abandoned_and_Insulted": "Flogisto y Metal (Abandonado e insultado)", - "Spring_of_Life": "Partícula virtual y Agua sólida (La fuente de la vida)", - "The_Land_of_Gold": "Arroz protéico e Ingredientes básicos (Tierra de oportunidades)", - "The_Blossom_in_the_Storm": "Líquido gaseoso y Semilla (Flores en la tormenta)", - "Legend_of_the_Puppet_Master": "Unidad de ábaco de jade y Componentes mecánicos abandonados (La leyenda del titiritero)", - "The_Wages_of_Humanity": "Extracto de hierbas medicinales y Cosecha tan alta como una persona (La paga de la humanidad)" + "Akashic_Records": "Material de EXP de conos de luz (Los Registros de Akasha)", + "The_Invisible_Hand": "Crédito (La mano invisible)", + "Abandoned_and_Insulted": "Flogisto & Metal (Abandonado e insultado)", + "Spring_of_Life": "Agua sólida & Partícula virtual (La fuente de la vida)", + "The_Land_of_Gold": "Ingredientes básicos & Arroz proteico (Tierra de oportunidades)", + "The_Blossom_in_the_Storm": "Líquido gaseoso & Semilla (Flores en la tormenta)", + "Legend_of_the_Puppet_Master": "Componentes mecánicos abandonados & Unidad de ábaco de jade (La leyenda del titiritero)", + "The_Wages_of_Humanity": "Cosecha tan alta como una persona & Extracto de hierbas medicinales (La paga de la humanidad)", + "Fragments_of_Illusory_Dreams": "Tranquilidad & Sueños rotos (Fragmentos de sueños ilusorios)", + "Scalpel_and_Screwdriver": "Engranaje oxidado & Muela vieja (Bisturí y destornillador)" }, "Name_2": { "name": "Preferencia de Encargo 2", "help": "", "Nine_Billion_Names": "Núcleo apagado (Nueve mil millones de nombres)", - "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucci´pon del destructor)", + "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucción del destructor)", "Winter_Soldiers": "Pin del guardia (Los guerreros del invierno)", "Born_to_Obey": "Componente antiguo (Creados para obedecer)", "Root_Out_the_Turpitude": "Brote verde inmortal (La raíz del mal)", "Fire_Lord_Inflames_Blades_of_War": "Componente artificial mecánico (Prendan los fuelles, fundan las armas)", + "A_Startling_Night_Terror": "Componente del acumulador de sueños (Pesadilla aterradora)", + "Tranquility_of_Vimala_bhumi": "Jirones de pensamientos (Limpieza y purificación)", "Nameless_Land_Nameless_People": "Material de EXP de personaje (Lugar anónimo, personas anónimas)", - "Akashic_Records": "Material de EXP de cono de luz (Los Registros de Akasha)", - "The_Invisible_Hand": "Créditos (La mano invisible)", - "Abandoned_and_Insulted": "Flogisto y Metal (Abandonado e insultado)", - "Spring_of_Life": "Partícula virtual y Agua sólida (La fuente de la vida)", - "The_Land_of_Gold": "Arroz protéico e Ingredientes básicos (Tierra de oportunidades)", - "The_Blossom_in_the_Storm": "Líquido gaseoso y Semilla (Flores en la tormenta)", - "Legend_of_the_Puppet_Master": "Unidad de ábaco de jade y Componentes mecánicos abandonados (La leyenda del titiritero)", - "The_Wages_of_Humanity": "Extracto de hierbas medicinales y Cosecha tan alta como una persona (La paga de la humanidad)" + "Akashic_Records": "Material de EXP de conos de luz (Los Registros de Akasha)", + "The_Invisible_Hand": "Crédito (La mano invisible)", + "Abandoned_and_Insulted": "Flogisto & Metal (Abandonado e insultado)", + "Spring_of_Life": "Agua sólida & Partícula virtual (La fuente de la vida)", + "The_Land_of_Gold": "Ingredientes básicos & Arroz proteico (Tierra de oportunidades)", + "The_Blossom_in_the_Storm": "Líquido gaseoso & Semilla (Flores en la tormenta)", + "Legend_of_the_Puppet_Master": "Componentes mecánicos abandonados & Unidad de ábaco de jade (La leyenda del titiritero)", + "The_Wages_of_Humanity": "Cosecha tan alta como una persona & Extracto de hierbas medicinales (La paga de la humanidad)", + "Fragments_of_Illusory_Dreams": "Tranquilidad & Sueños rotos (Fragmentos de sueños ilusorios)", + "Scalpel_and_Screwdriver": "Engranaje oxidado & Muela vieja (Bisturí y destornillador)" }, "Name_3": { "name": "Preferencia de Encargo 3", "help": "", "Nine_Billion_Names": "Núcleo apagado (Nueve mil millones de nombres)", - "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucci´pon del destructor)", + "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucción del destructor)", "Winter_Soldiers": "Pin del guardia (Los guerreros del invierno)", "Born_to_Obey": "Componente antiguo (Creados para obedecer)", "Root_Out_the_Turpitude": "Brote verde inmortal (La raíz del mal)", "Fire_Lord_Inflames_Blades_of_War": "Componente artificial mecánico (Prendan los fuelles, fundan las armas)", + "A_Startling_Night_Terror": "Componente del acumulador de sueños (Pesadilla aterradora)", + "Tranquility_of_Vimala_bhumi": "Jirones de pensamientos (Limpieza y purificación)", "Nameless_Land_Nameless_People": "Material de EXP de personaje (Lugar anónimo, personas anónimas)", - "Akashic_Records": "Material de EXP de cono de luz (Los Registros de Akasha)", - "The_Invisible_Hand": "Créditos (La mano invisible)", - "Abandoned_and_Insulted": "Flogisto y Metal (Abandonado e insultado)", - "Spring_of_Life": "Partícula virtual y Agua sólida (La fuente de la vida)", - "The_Land_of_Gold": "Arroz protéico e Ingredientes básicos (Tierra de oportunidades)", - "The_Blossom_in_the_Storm": "Líquido gaseoso y Semilla (Flores en la tormenta)", - "Legend_of_the_Puppet_Master": "Unidad de ábaco de jade y Componentes mecánicos abandonados (La leyenda del titiritero)", - "The_Wages_of_Humanity": "Extracto de hierbas medicinales y Cosecha tan alta como una persona (La paga de la humanidad)" + "Akashic_Records": "Material de EXP de conos de luz (Los Registros de Akasha)", + "The_Invisible_Hand": "Crédito (La mano invisible)", + "Abandoned_and_Insulted": "Flogisto & Metal (Abandonado e insultado)", + "Spring_of_Life": "Agua sólida & Partícula virtual (La fuente de la vida)", + "The_Land_of_Gold": "Ingredientes básicos & Arroz proteico (Tierra de oportunidades)", + "The_Blossom_in_the_Storm": "Líquido gaseoso & Semilla (Flores en la tormenta)", + "Legend_of_the_Puppet_Master": "Componentes mecánicos abandonados & Unidad de ábaco de jade (La leyenda del titiritero)", + "The_Wages_of_Humanity": "Cosecha tan alta como una persona & Extracto de hierbas medicinales (La paga de la humanidad)", + "Fragments_of_Illusory_Dreams": "Tranquilidad & Sueños rotos (Fragmentos de sueños ilusorios)", + "Scalpel_and_Screwdriver": "Engranaje oxidado & Muela vieja (Bisturí y destornillador)" }, "Name_4": { "name": "Preferencia de Encargo 4", "help": "", "Nine_Billion_Names": "Núcleo apagado (Nueve mil millones de nombres)", - "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucci´pon del destructor)", + "Destruction_of_the_Destroyer": "Instinto del ladrón (La destrucción del destructor)", "Winter_Soldiers": "Pin del guardia (Los guerreros del invierno)", "Born_to_Obey": "Componente antiguo (Creados para obedecer)", "Root_Out_the_Turpitude": "Brote verde inmortal (La raíz del mal)", "Fire_Lord_Inflames_Blades_of_War": "Componente artificial mecánico (Prendan los fuelles, fundan las armas)", + "A_Startling_Night_Terror": "Componente del acumulador de sueños (Pesadilla aterradora)", + "Tranquility_of_Vimala_bhumi": "Jirones de pensamientos (Limpieza y purificación)", "Nameless_Land_Nameless_People": "Material de EXP de personaje (Lugar anónimo, personas anónimas)", - "Akashic_Records": "Material de EXP de cono de luz (Los Registros de Akasha)", - "The_Invisible_Hand": "Créditos (La mano invisible)", - "Abandoned_and_Insulted": "Flogisto y Metal (Abandonado e insultado)", - "Spring_of_Life": "Partícula virtual y Agua sólida (La fuente de la vida)", - "The_Land_of_Gold": "Arroz protéico e Ingredientes básicos (Tierra de oportunidades)", - "The_Blossom_in_the_Storm": "Líquido gaseoso y Semilla (Flores en la tormenta)", - "Legend_of_the_Puppet_Master": "Unidad de ábaco de jade y Componentes mecánicos abandonados (La leyenda del titiritero)", - "The_Wages_of_Humanity": "Extracto de hierbas medicinales y Cosecha tan alta como una persona (La paga de la humanidad)" + "Akashic_Records": "Material de EXP de conos de luz (Los Registros de Akasha)", + "The_Invisible_Hand": "Crédito (La mano invisible)", + "Abandoned_and_Insulted": "Flogisto & Metal (Abandonado e insultado)", + "Spring_of_Life": "Agua sólida & Partícula virtual (La fuente de la vida)", + "The_Land_of_Gold": "Ingredientes básicos & Arroz proteico (Tierra de oportunidades)", + "The_Blossom_in_the_Storm": "Líquido gaseoso & Semilla (Flores en la tormenta)", + "Legend_of_the_Puppet_Master": "Componentes mecánicos abandonados & Unidad de ábaco de jade (La leyenda del titiritero)", + "The_Wages_of_Humanity": "Cosecha tan alta como una persona & Extracto de hierbas medicinales (La paga de la humanidad)", + "Fragments_of_Illusory_Dreams": "Tranquilidad & Sueños rotos (Fragmentos de sueños ilusorios)", + "Scalpel_and_Screwdriver": "Engranaje oxidado & Muela vieja (Bisturí y destornillador)" }, "Duration": { "name": "Duración del encargo", @@ -974,6 +1028,14 @@ "name": "Clic de diálogo", "help": "Monitorear el juego, hacer clic automáticamente en el diálogo, chatear por teléfono y bendecir en el universo simulado (sigue la configuración de tareas del universo simulado)", "True": "Activado" + }, + "AimClicker": { + "name": "Haz clic en Objetos y enemigos apuntados", + "help": "", + "item_enemy": "Haz clic en elementos y enemigos", + "item": "Haz clic solo en elementos", + "enemy": "Haz clic solo en enemigos", + "do_not_click": "No hacer clic" } }, "Gui": { diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index cebc93a5d..5b11ec40f 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -247,66 +247,88 @@ "Name": { "name": "Dungeon.Name.name", "help": "Dungeon.Name.help", - "Calyx_Golden_Memories": "疑似花萼(金)・回憶の蕾", - "Calyx_Golden_Aether": "疑似花萼(金)・エーテルの蕾", - "Calyx_Golden_Treasures": "疑似花萼(金)・秘蔵の蕾", - "Calyx_Crimson_Destruction": "疑似花萼(赤)・壊滅の蕾", - "Calyx_Crimson_Preservation": "疑似花萼(赤)・存護の蕾", - "Calyx_Crimson_The_Hunt": "疑似花萼(赤)・巡狩の蕾", - "Calyx_Crimson_Abundance": "疑似花萼(赤)・豊穣の蕾", - "Calyx_Crimson_Erudition": "疑似花萼(赤)・知恵の蕾", - "Calyx_Crimson_Harmony": "疑似花萼(赤)・調和の蕾", - "Calyx_Crimson_Nihility": "疑似花萼(赤)・虚無の蕾", - "Stagnant_Shadow_Quanta": "キャラクター昇格素材:量子(銀狼 / ゼーレ / 青雀)", - "Stagnant_Shadow_Gust": "キャラクター昇格素材:風(丹恒 / ブローニャ / サンポ)", - "Stagnant_Shadow_Fulmination": "キャラクター昇格素材:雷(アーラン / セーバル / 停雲 / 白露)", - "Stagnant_Shadow_Blaze": "キャラクター昇格素材:炎(姫子 / アスター / フック)", + "Calyx_Golden_Memories_Jarilo_VI": "素材:役割経験(回憶の蕾・ヤリーロ-Ⅵ):", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "素材:役割経験(回憶の蕾・仙舟羅浮):", + "Calyx_Golden_Memories_Penacony": "素材:役割経験(回憶の蕾・ピノコニー):", + "Calyx_Golden_Aether_Jarilo_VI": "素材:武器経験(エーテルの蕾・ヤリーロ-Ⅵ):", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "素材:武器経験(エーテルの蕾・仙舟羅浮):", + "Calyx_Golden_Aether_Penacony": "素材:武器経験(エーテルの蕾・ピノコニー):", + "Calyx_Golden_Treasures_Jarilo_VI": "素材:クレジット(秘蔵の蕾・ヤリーロ-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "素材:クレジット(秘蔵の蕾・仙舟羅浮)", + "Calyx_Golden_Treasures_Penacony": "素材:クレジット(秘蔵の蕾・ピノコニー)", + "Calyx_Crimson_Destruction_Herta_StorageZone": "軌跡素材:壊滅(収容部分)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "軌跡素材:壊滅(鱗淵境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "軌跡素材:存護(サポート部分)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "軌跡素材:巡狩(郊外雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "軌跡素材:豊穣(外縁通路)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "軌跡素材:知恵(リベットタウン)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "軌跡素材:調和(機械集落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "軌跡素材:調和(ホテル・レバリー-夢境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "軌跡素材:虚無(大鉱区)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "軌跡素材:虚無(丹鼎司)", "Stagnant_Shadow_Spike": "キャラクター昇格素材:物理(ナターシャ / クラーラ / ルカ / 素裳)", - "Stagnant_Shadow_Rime": "キャラクター昇格素材:氷(三月なのか / ヘルタ / ジェパード / ペラ)", - "Stagnant_Shadow_Mirage": "キャラクター昇格素材:虚数(ヴェルト / 羅刹 / 御空)", - "Stagnant_Shadow_Icicle": "キャラクター昇格素材:氷(彦卿 / 鏡流 / ルアン・メェイ)", - "Stagnant_Shadow_Doom": "キャラクター昇格素材:雷(カフカ / 景元)", - "Stagnant_Shadow_Puppetry": "キャラクター昇格素材:虚数(丹恒・飲月 / Dr.レイシオ)", - "Stagnant_Shadow_Abomination": "キャラクター昇格素材:量子(リンクス / 符玄 / 雪衣)", - "Stagnant_Shadow_Scorch": "キャラクター昇格素材:炎(桂乃芬 / トパーズ&カブ)", - "Stagnant_Shadow_Celestial": "キャラクター昇格素材:風(刃 / フォフォ)", "Stagnant_Shadow_Perdition": "キャラクター昇格素材:物理(寒鴉 / アルジェンティ)", - "Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路", - "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路", - "Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路", - "Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路", - "Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路", - "Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路", - "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路", - "Cavern_of_Corrosion_Path_of_Darkness": "侵蝕トンネル・幽冥の路" + "Stagnant_Shadow_Blaze": "キャラクター昇格素材:炎(姫子 / アスター / フック)", + "Stagnant_Shadow_Scorch": "キャラクター昇格素材:炎(桂乃芬 / トパーズ&カブ)", + "Stagnant_Shadow_Rime": "キャラクター昇格素材:氷(三月なのか / ヘルタ / ジェパード / ペラ)", + "Stagnant_Shadow_Icicle": "キャラクター昇格素材:氷(彦卿 / 鏡流 / ルアン・メェイ)", + "Stagnant_Shadow_Nectar": "キャラクター昇格素材:氷(ミーシャ)", + "Stagnant_Shadow_Fulmination": "キャラクター昇格素材:雷(アーラン / セーバル / 停雲 / 白露)", + "Stagnant_Shadow_Doom": "キャラクター昇格素材:雷(カフカ / 景元)", + "Stagnant_Shadow_Gust": "キャラクター昇格素材:風(丹恒 / ブローニャ / サンポ)", + "Stagnant_Shadow_Celestial": "キャラクター昇格素材:風(刃 / フォフォ / ブラックスワン)", + "Stagnant_Shadow_Quanta": "キャラクター昇格素材:量子(銀狼 / ゼーレ / 青雀)", + "Stagnant_Shadow_Abomination": "キャラクター昇格素材:量子(リンクス / 符玄 / 雪衣)", + "Stagnant_Shadow_Roast": "キャラクター昇格素材:量子(花火)", + "Stagnant_Shadow_Mirage": "キャラクター昇格素材:虚数(ヴェルト / 羅刹 / 御空)", + "Stagnant_Shadow_Puppetry": "キャラクター昇格素材:虚数(丹恒・飲月 / Dr.レイシオ)", + "Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路(侵蝕トンネル・霜風の路)", + "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路(侵蝕トンネル・迅拳の路)", + "Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路(侵蝕トンネル・漂泊の路)", + "Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路(侵蝕トンネル・睿治の路)", + "Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路(侵蝕トンネル・聖頌の路)", + "Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路(侵蝕トンネル・野焔の路)", + "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路(侵蝕トンネル・薬使の路)", + "Cavern_of_Corrosion_Path_of_Darkness": "侵蝕トンネル・幽冥の路(侵蝕トンネル・幽冥の路)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "侵蝕トンネル・夢潜の路(侵蝕トンネル・夢潜の路)" }, "NameAtDoubleCalyx": { "name": "Dungeon.NameAtDoubleCalyx.name", "help": "Dungeon.NameAtDoubleCalyx.help", "do_not_participate": "do_not_participate", - "Calyx_Golden_Memories": "疑似花萼(金)・回憶の蕾", - "Calyx_Golden_Aether": "疑似花萼(金)・エーテルの蕾", - "Calyx_Golden_Treasures": "疑似花萼(金)・秘蔵の蕾", - "Calyx_Crimson_Destruction": "疑似花萼(赤)・壊滅の蕾", - "Calyx_Crimson_Preservation": "疑似花萼(赤)・存護の蕾", - "Calyx_Crimson_The_Hunt": "疑似花萼(赤)・巡狩の蕾", - "Calyx_Crimson_Abundance": "疑似花萼(赤)・豊穣の蕾", - "Calyx_Crimson_Erudition": "疑似花萼(赤)・知恵の蕾", - "Calyx_Crimson_Harmony": "疑似花萼(赤)・調和の蕾", - "Calyx_Crimson_Nihility": "疑似花萼(赤)・虚無の蕾" + "Calyx_Golden_Memories_Jarilo_VI": "素材:役割経験(回憶の蕾・ヤリーロ-Ⅵ):", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "素材:役割経験(回憶の蕾・仙舟羅浮):", + "Calyx_Golden_Memories_Penacony": "素材:役割経験(回憶の蕾・ピノコニー):", + "Calyx_Golden_Aether_Jarilo_VI": "素材:武器経験(エーテルの蕾・ヤリーロ-Ⅵ):", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "素材:武器経験(エーテルの蕾・仙舟羅浮):", + "Calyx_Golden_Aether_Penacony": "素材:武器経験(エーテルの蕾・ピノコニー):", + "Calyx_Golden_Treasures_Jarilo_VI": "素材:クレジット(秘蔵の蕾・ヤリーロ-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "素材:クレジット(秘蔵の蕾・仙舟羅浮)", + "Calyx_Golden_Treasures_Penacony": "素材:クレジット(秘蔵の蕾・ピノコニー)", + "Calyx_Crimson_Destruction_Herta_StorageZone": "軌跡素材:壊滅(収容部分)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "軌跡素材:壊滅(鱗淵境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "軌跡素材:存護(サポート部分)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "軌跡素材:巡狩(郊外雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "軌跡素材:豊穣(外縁通路)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "軌跡素材:知恵(リベットタウン)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "軌跡素材:調和(機械集落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "軌跡素材:調和(ホテル・レバリー-夢境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "軌跡素材:虚無(大鉱区)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "軌跡素材:虚無(丹鼎司)" }, "NameAtDoubleRelic": { "name": "Dungeon.NameAtDoubleRelic.name", "help": "Dungeon.NameAtDoubleRelic.help", "do_not_participate": "do_not_participate", - "Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路", - "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路", - "Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路", - "Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路", - "Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路", - "Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路", - "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路", - "Cavern_of_Corrosion_Path_of_Darkness": "侵蝕トンネル・幽冥の路" + "Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路(侵蝕トンネル・霜風の路)", + "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路(侵蝕トンネル・迅拳の路)", + "Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路(侵蝕トンネル・漂泊の路)", + "Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路(侵蝕トンネル・睿治の路)", + "Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路(侵蝕トンネル・聖頌の路)", + "Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路(侵蝕トンネル・野焔の路)", + "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路(侵蝕トンネル・薬使の路)", + "Cavern_of_Corrosion_Path_of_Darkness": "侵蝕トンネル・幽冥の路(侵蝕トンネル・幽冥の路)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "侵蝕トンネル・夢潜の路(侵蝕トンネル・夢潜の路)" }, "Team": { "name": "Dungeon.Team.name", @@ -331,53 +353,65 @@ "name": "DungeonDaily.CalyxGolden.name", "help": "DungeonDaily.CalyxGolden.help", "do_not_achieve": "do_not_achieve", - "Calyx_Golden_Memories": "疑似花萼(金)・回憶の蕾", - "Calyx_Golden_Aether": "疑似花萼(金)・エーテルの蕾", - "Calyx_Golden_Treasures": "疑似花萼(金)・秘蔵の蕾" + "Calyx_Golden_Memories_Jarilo_VI": "素材:役割経験(回憶の蕾・ヤリーロ-Ⅵ):", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "素材:役割経験(回憶の蕾・仙舟羅浮):", + "Calyx_Golden_Memories_Penacony": "素材:役割経験(回憶の蕾・ピノコニー):", + "Calyx_Golden_Aether_Jarilo_VI": "素材:武器経験(エーテルの蕾・ヤリーロ-Ⅵ):", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "素材:武器経験(エーテルの蕾・仙舟羅浮):", + "Calyx_Golden_Aether_Penacony": "素材:武器経験(エーテルの蕾・ピノコニー):", + "Calyx_Golden_Treasures_Jarilo_VI": "素材:クレジット(秘蔵の蕾・ヤリーロ-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "素材:クレジット(秘蔵の蕾・仙舟羅浮)", + "Calyx_Golden_Treasures_Penacony": "素材:クレジット(秘蔵の蕾・ピノコニー)" }, "CalyxCrimson": { "name": "DungeonDaily.CalyxCrimson.name", "help": "DungeonDaily.CalyxCrimson.help", "do_not_achieve": "do_not_achieve", - "Calyx_Crimson_Destruction": "疑似花萼(赤)・壊滅の蕾", - "Calyx_Crimson_Preservation": "疑似花萼(赤)・存護の蕾", - "Calyx_Crimson_The_Hunt": "疑似花萼(赤)・巡狩の蕾", - "Calyx_Crimson_Abundance": "疑似花萼(赤)・豊穣の蕾", - "Calyx_Crimson_Erudition": "疑似花萼(赤)・知恵の蕾", - "Calyx_Crimson_Harmony": "疑似花萼(赤)・調和の蕾", - "Calyx_Crimson_Nihility": "疑似花萼(赤)・虚無の蕾" + "Calyx_Crimson_Destruction_Herta_StorageZone": "軌跡素材:壊滅(収容部分)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "軌跡素材:壊滅(鱗淵境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "軌跡素材:存護(サポート部分)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "軌跡素材:巡狩(郊外雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "軌跡素材:豊穣(外縁通路)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "軌跡素材:知恵(リベットタウン)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "軌跡素材:調和(機械集落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "軌跡素材:調和(ホテル・レバリー-夢境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "軌跡素材:虚無(大鉱区)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "軌跡素材:虚無(丹鼎司)" }, "StagnantShadow": { "name": "DungeonDaily.StagnantShadow.name", "help": "DungeonDaily.StagnantShadow.help", "do_not_achieve": "do_not_achieve", - "Stagnant_Shadow_Quanta": "キャラクター昇格素材:量子(銀狼 / ゼーレ / 青雀)", - "Stagnant_Shadow_Gust": "キャラクター昇格素材:風(丹恒 / ブローニャ / サンポ)", - "Stagnant_Shadow_Fulmination": "キャラクター昇格素材:雷(アーラン / セーバル / 停雲 / 白露)", - "Stagnant_Shadow_Blaze": "キャラクター昇格素材:炎(姫子 / アスター / フック)", "Stagnant_Shadow_Spike": "キャラクター昇格素材:物理(ナターシャ / クラーラ / ルカ / 素裳)", - "Stagnant_Shadow_Rime": "キャラクター昇格素材:氷(三月なのか / ヘルタ / ジェパード / ペラ)", - "Stagnant_Shadow_Mirage": "キャラクター昇格素材:虚数(ヴェルト / 羅刹 / 御空)", - "Stagnant_Shadow_Icicle": "キャラクター昇格素材:氷(彦卿 / 鏡流 / ルアン・メェイ)", - "Stagnant_Shadow_Doom": "キャラクター昇格素材:雷(カフカ / 景元)", - "Stagnant_Shadow_Puppetry": "キャラクター昇格素材:虚数(丹恒・飲月 / Dr.レイシオ)", - "Stagnant_Shadow_Abomination": "キャラクター昇格素材:量子(リンクス / 符玄 / 雪衣)", + "Stagnant_Shadow_Perdition": "キャラクター昇格素材:物理(寒鴉 / アルジェンティ)", + "Stagnant_Shadow_Blaze": "キャラクター昇格素材:炎(姫子 / アスター / フック)", "Stagnant_Shadow_Scorch": "キャラクター昇格素材:炎(桂乃芬 / トパーズ&カブ)", - "Stagnant_Shadow_Celestial": "キャラクター昇格素材:風(刃 / フォフォ)", - "Stagnant_Shadow_Perdition": "キャラクター昇格素材:物理(寒鴉 / アルジェンティ)" + "Stagnant_Shadow_Rime": "キャラクター昇格素材:氷(三月なのか / ヘルタ / ジェパード / ペラ)", + "Stagnant_Shadow_Icicle": "キャラクター昇格素材:氷(彦卿 / 鏡流 / ルアン・メェイ)", + "Stagnant_Shadow_Nectar": "キャラクター昇格素材:氷(ミーシャ)", + "Stagnant_Shadow_Fulmination": "キャラクター昇格素材:雷(アーラン / セーバル / 停雲 / 白露)", + "Stagnant_Shadow_Doom": "キャラクター昇格素材:雷(カフカ / 景元)", + "Stagnant_Shadow_Gust": "キャラクター昇格素材:風(丹恒 / ブローニャ / サンポ)", + "Stagnant_Shadow_Celestial": "キャラクター昇格素材:風(刃 / フォフォ / ブラックスワン)", + "Stagnant_Shadow_Quanta": "キャラクター昇格素材:量子(銀狼 / ゼーレ / 青雀)", + "Stagnant_Shadow_Abomination": "キャラクター昇格素材:量子(リンクス / 符玄 / 雪衣)", + "Stagnant_Shadow_Roast": "キャラクター昇格素材:量子(花火)", + "Stagnant_Shadow_Mirage": "キャラクター昇格素材:虚数(ヴェルト / 羅刹 / 御空)", + "Stagnant_Shadow_Puppetry": "キャラクター昇格素材:虚数(丹恒・飲月 / Dr.レイシオ)" }, "CavernOfCorrosion": { "name": "DungeonDaily.CavernOfCorrosion.name", "help": "DungeonDaily.CavernOfCorrosion.help", "do_not_achieve": "do_not_achieve", - "Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路", - "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路", - "Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路", - "Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路", - "Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路", - "Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路", - "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路", - "Cavern_of_Corrosion_Path_of_Darkness": "侵蝕トンネル・幽冥の路" + "Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路(侵蝕トンネル・霜風の路)", + "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路(侵蝕トンネル・迅拳の路)", + "Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路(侵蝕トンネル・漂泊の路)", + "Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路(侵蝕トンネル・睿治の路)", + "Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路(侵蝕トンネル・聖頌の路)", + "Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路(侵蝕トンネル・野焔の路)", + "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路(侵蝕トンネル・薬使の路)", + "Cavern_of_Corrosion_Path_of_Darkness": "侵蝕トンネル・幽冥の路(侵蝕トンネル・幽冥の路)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "侵蝕トンネル・夢潜の路(侵蝕トンネル・夢潜の路)" } }, "DungeonSupport": { @@ -400,11 +434,13 @@ "Arlan": "アーラン", "Asta": "アスター", "Bailu": "白露", + "BlackSwan": "ブラックスワン", "Blade": "刃", "Bronya": "ブローニャ", "Clara": "クラーラ", "DanHeng": "丹恒", "DanHengImbibitorLunae": "丹恒・飲月", + "DrRatio": "Dr.レイシオ", "FuXuan": "符玄", "Gepard": "ジェパード", "Guinaifen": "桂乃芬", @@ -420,6 +456,7 @@ "Luocha": "羅刹", "Lynx": "リンクス", "March7th": "三月なのか", + "Misha": "ミーシャ", "Natasha": "ナターシャ", "Pela": "ペラ", "Qingque": "青雀", @@ -428,6 +465,7 @@ "Seele": "ゼーレ", "Serval": "セーバル", "SilverWolf": "銀狼", + "Sparkle": "花火", "Sushang": "素裳", "Tingyun": "停雲", "TopazNumby": "トパーズ&カブ", @@ -760,15 +798,19 @@ "Born_to_Obey": "古代パーツ(生まれながらに服従する)", "Root_Out_the_Turpitude": "永寿の萌芽(悪孽を根絶やしに)", "Fire_Lord_Inflames_Blades_of_War": "工造機関(剣戟を焼却する火帝炉)", - "Nameless_Land_Nameless_People": "キャラクターの経験値素材(無名の地、無名の人)", - "Akashic_Records": "光円錐強化素材(アーカーシャの記録)", + "A_Startling_Night_Terror": "ドリームコレクションパーツ(魂震える悪夢)", + "Tranquility_of_Vimala_bhumi": "思考の粉末(離垢清浄)", + "Nameless_Land_Nameless_People": "キャラクター経験値素材(無名の地、無名の人)", + "Akashic_Records": "光円錐経験値素材(アーカーシャの記録)", "The_Invisible_Hand": "信用ポイント(見えざる手)", - "Abandoned_and_Insulted": "燃素と金属(捨てられしものと傷つけられしもの)", - "Spring_of_Life": "仮想粒子と固形純水(生命の泉)", - "The_Land_of_Gold": "タンパク米と基本食材(黄金の大地)", - "The_Blossom_in_the_Storm": "気態流体と種子(嵐の中で咲き誇る花)", - "Legend_of_the_Puppet_Master": "玉兆単元&廃棄された機巧部品(傀儡師伝説)", - "The_Wages_of_Humanity": "薬草抽出物&一人稲(人類扶養)" + "Abandoned_and_Insulted": "燃素 & 金属(捨てられしものと傷つけられしもの)", + "Spring_of_Life": "固形純水 & 仮想粒子(生命の泉)", + "The_Land_of_Gold": "基本食材 & タンパク米(黄金の大地)", + "The_Blossom_in_the_Storm": "気態流体 & 種子(嵐の中で咲き誇る花)", + "Legend_of_the_Puppet_Master": "廃棄された機巧部品 & 玉兆単元(傀儡師伝説)", + "The_Wages_of_Humanity": "一人稲 & 薬草抽出物(人類扶養)", + "Fragments_of_Illusory_Dreams": "安逸 & 砕けた夢(幻夢の残片)", + "Scalpel_and_Screwdriver": "錆びた歯車 & 古びた大臼歯(メスとスクリュードライバー)" }, "Name_2": { "name": "依頼 2", @@ -779,15 +821,19 @@ "Born_to_Obey": "古代パーツ(生まれながらに服従する)", "Root_Out_the_Turpitude": "永寿の萌芽(悪孽を根絶やしに)", "Fire_Lord_Inflames_Blades_of_War": "工造機関(剣戟を焼却する火帝炉)", - "Nameless_Land_Nameless_People": "キャラクターの経験値素材(無名の地、無名の人)", - "Akashic_Records": "光円錐強化素材(アーカーシャの記録)", + "A_Startling_Night_Terror": "ドリームコレクションパーツ(魂震える悪夢)", + "Tranquility_of_Vimala_bhumi": "思考の粉末(離垢清浄)", + "Nameless_Land_Nameless_People": "キャラクター経験値素材(無名の地、無名の人)", + "Akashic_Records": "光円錐経験値素材(アーカーシャの記録)", "The_Invisible_Hand": "信用ポイント(見えざる手)", - "Abandoned_and_Insulted": "燃素と金属(捨てられしものと傷つけられしもの)", - "Spring_of_Life": "仮想粒子と固形純水(生命の泉)", - "The_Land_of_Gold": "タンパク米と基本食材(黄金の大地)", - "The_Blossom_in_the_Storm": "気態流体と種子(嵐の中で咲き誇る花)", - "Legend_of_the_Puppet_Master": "玉兆単元&廃棄された機巧部品(傀儡師伝説)", - "The_Wages_of_Humanity": "薬草抽出物&一人稲(人類扶養)" + "Abandoned_and_Insulted": "燃素 & 金属(捨てられしものと傷つけられしもの)", + "Spring_of_Life": "固形純水 & 仮想粒子(生命の泉)", + "The_Land_of_Gold": "基本食材 & タンパク米(黄金の大地)", + "The_Blossom_in_the_Storm": "気態流体 & 種子(嵐の中で咲き誇る花)", + "Legend_of_the_Puppet_Master": "廃棄された機巧部品 & 玉兆単元(傀儡師伝説)", + "The_Wages_of_Humanity": "一人稲 & 薬草抽出物(人類扶養)", + "Fragments_of_Illusory_Dreams": "安逸 & 砕けた夢(幻夢の残片)", + "Scalpel_and_Screwdriver": "錆びた歯車 & 古びた大臼歯(メスとスクリュードライバー)" }, "Name_3": { "name": "依頼 3", @@ -798,15 +844,19 @@ "Born_to_Obey": "古代パーツ(生まれながらに服従する)", "Root_Out_the_Turpitude": "永寿の萌芽(悪孽を根絶やしに)", "Fire_Lord_Inflames_Blades_of_War": "工造機関(剣戟を焼却する火帝炉)", - "Nameless_Land_Nameless_People": "キャラクターの経験値素材(無名の地、無名の人)", - "Akashic_Records": "光円錐強化素材(アーカーシャの記録)", + "A_Startling_Night_Terror": "ドリームコレクションパーツ(魂震える悪夢)", + "Tranquility_of_Vimala_bhumi": "思考の粉末(離垢清浄)", + "Nameless_Land_Nameless_People": "キャラクター経験値素材(無名の地、無名の人)", + "Akashic_Records": "光円錐経験値素材(アーカーシャの記録)", "The_Invisible_Hand": "信用ポイント(見えざる手)", - "Abandoned_and_Insulted": "燃素と金属(捨てられしものと傷つけられしもの)", - "Spring_of_Life": "仮想粒子と固形純水(生命の泉)", - "The_Land_of_Gold": "タンパク米と基本食材(黄金の大地)", - "The_Blossom_in_the_Storm": "気態流体と種子(嵐の中で咲き誇る花)", - "Legend_of_the_Puppet_Master": "玉兆単元&廃棄された機巧部品(傀儡師伝説)", - "The_Wages_of_Humanity": "薬草抽出物&一人稲(人類扶養)" + "Abandoned_and_Insulted": "燃素 & 金属(捨てられしものと傷つけられしもの)", + "Spring_of_Life": "固形純水 & 仮想粒子(生命の泉)", + "The_Land_of_Gold": "基本食材 & タンパク米(黄金の大地)", + "The_Blossom_in_the_Storm": "気態流体 & 種子(嵐の中で咲き誇る花)", + "Legend_of_the_Puppet_Master": "廃棄された機巧部品 & 玉兆単元(傀儡師伝説)", + "The_Wages_of_Humanity": "一人稲 & 薬草抽出物(人類扶養)", + "Fragments_of_Illusory_Dreams": "安逸 & 砕けた夢(幻夢の残片)", + "Scalpel_and_Screwdriver": "錆びた歯車 & 古びた大臼歯(メスとスクリュードライバー)" }, "Name_4": { "name": "依頼 4", @@ -817,15 +867,19 @@ "Born_to_Obey": "古代パーツ(生まれながらに服従する)", "Root_Out_the_Turpitude": "永寿の萌芽(悪孽を根絶やしに)", "Fire_Lord_Inflames_Blades_of_War": "工造機関(剣戟を焼却する火帝炉)", - "Nameless_Land_Nameless_People": "キャラクターの経験値素材(無名の地、無名の人)", - "Akashic_Records": "光円錐強化素材(アーカーシャの記録)", + "A_Startling_Night_Terror": "ドリームコレクションパーツ(魂震える悪夢)", + "Tranquility_of_Vimala_bhumi": "思考の粉末(離垢清浄)", + "Nameless_Land_Nameless_People": "キャラクター経験値素材(無名の地、無名の人)", + "Akashic_Records": "光円錐経験値素材(アーカーシャの記録)", "The_Invisible_Hand": "信用ポイント(見えざる手)", - "Abandoned_and_Insulted": "燃素と金属(捨てられしものと傷つけられしもの)", - "Spring_of_Life": "仮想粒子と固形純水(生命の泉)", - "The_Land_of_Gold": "タンパク米と基本食材(黄金の大地)", - "The_Blossom_in_the_Storm": "気態流体と種子(嵐の中で咲き誇る花)", - "Legend_of_the_Puppet_Master": "玉兆単元&廃棄された機巧部品(傀儡師伝説)", - "The_Wages_of_Humanity": "薬草抽出物&一人稲(人類扶養)" + "Abandoned_and_Insulted": "燃素 & 金属(捨てられしものと傷つけられしもの)", + "Spring_of_Life": "固形純水 & 仮想粒子(生命の泉)", + "The_Land_of_Gold": "基本食材 & タンパク米(黄金の大地)", + "The_Blossom_in_the_Storm": "気態流体 & 種子(嵐の中で咲き誇る花)", + "Legend_of_the_Puppet_Master": "廃棄された機巧部品 & 玉兆単元(傀儡師伝説)", + "The_Wages_of_Humanity": "一人稲 & 薬草抽出物(人類扶養)", + "Fragments_of_Illusory_Dreams": "安逸 & 砕けた夢(幻夢の残片)", + "Scalpel_and_Screwdriver": "錆びた歯車 & 古びた大臼歯(メスとスクリュードライバー)" }, "Duration": { "name": "派遣時間", @@ -974,6 +1028,14 @@ "name": "Daemon.Enable.name", "help": "Daemon.Enable.help", "True": "True" + }, + "AimClicker": { + "name": "Daemon.AimClicker.name", + "help": "Daemon.AimClicker.help", + "item_enemy": "item_enemy", + "item": "item", + "enemy": "enemy", + "do_not_click": "do_not_click" } }, "Gui": { diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index dc0f2ed5b..d8dee067a 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -247,30 +247,41 @@ "Name": { "name": "副本名称", "help": "默认打本设置", - "Calyx_Golden_Memories": "材料:角色经验(回忆之蕾•拟造花萼金)", - "Calyx_Golden_Aether": "材料:武器经验(以太之蕾•拟造花萼金)", - "Calyx_Golden_Treasures": "材料:信用点(藏珍之蕾•拟造花萼金)", - "Calyx_Crimson_Destruction": "行迹材料:毁灭(毁灭之蕾•拟造花萼赤)", - "Calyx_Crimson_Preservation": "行迹材料:存护(存护之蕾•拟造花萼赤)", - "Calyx_Crimson_The_Hunt": "行迹材料:巡猎(巡猎之蕾•拟造花萼赤)", - "Calyx_Crimson_Abundance": "行迹材料:丰饶(丰饶之蕾•拟造花萼赤)", - "Calyx_Crimson_Erudition": "行迹材料:智识(智识之蕾•拟造花萼赤)", - "Calyx_Crimson_Harmony": "行迹材料:同谐(同谐之蕾•拟造花萼赤)", - "Calyx_Crimson_Nihility": "行迹材料:虚无(虚无之蕾•拟造花萼赤)", - "Stagnant_Shadow_Quanta": "角色晋阶材料:量子(银狼 / 希儿 / 青雀)", - "Stagnant_Shadow_Gust": "角色晋阶材料:风(丹恒 / 布洛妮娅 / 桑博)", - "Stagnant_Shadow_Fulmination": "角色晋阶材料:雷(阿兰 / 希露瓦 / 停云 / 白露)", - "Stagnant_Shadow_Blaze": "角色晋阶材料:火(姬子 / 艾丝妲 / 虎克)", + "Calyx_Golden_Memories_Jarilo_VI": "材料:角色经验(回忆之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "材料:角色经验(回忆之蕾•仙舟罗浮)", + "Calyx_Golden_Memories_Penacony": "材料:角色经验(回忆之蕾•匹诺康尼)", + "Calyx_Golden_Aether_Jarilo_VI": "材料:武器经验(以太之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "材料:武器经验(以太之蕾•仙舟罗浮)", + "Calyx_Golden_Aether_Penacony": "材料:武器经验(以太之蕾•匹诺康尼)", + "Calyx_Golden_Treasures_Jarilo_VI": "材料:信用点(藏珍之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "材料:信用点(藏珍之蕾•仙舟罗浮)", + "Calyx_Golden_Treasures_Penacony": "材料:信用点(藏珍之蕾•匹诺康尼)", + "Calyx_Crimson_Destruction_Herta_StorageZone": "行迹材料:毁灭(收容舱段)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "行迹材料:毁灭(鳞渊境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "行迹材料:存护(支援舱段)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "行迹材料:巡猎(城郊雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "行迹材料:丰饶(边缘通路)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "行迹材料:智识(铆钉镇)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "行迹材料:同谐(机械聚落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "行迹材料:同谐(白日梦酒店-梦境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "行迹材料:虚无(大矿区)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "行迹材料:虚无(丹鼎司)", "Stagnant_Shadow_Spike": "角色晋阶材料:物理(娜塔莎 / 克拉拉 / 卢卡 / 素裳)", - "Stagnant_Shadow_Rime": "角色晋阶材料:冰(三月七 / 黑塔 / 杰帕德 / 佩拉)", - "Stagnant_Shadow_Mirage": "角色晋阶材料:虚数(瓦尔特 / 罗刹 / 驭空)", - "Stagnant_Shadow_Icicle": "角色晋阶材料:冰(彦卿 / 镜流 / 阮•梅)", - "Stagnant_Shadow_Doom": "角色晋阶材料:雷(卡芙卡 / 景元)", - "Stagnant_Shadow_Puppetry": "角色晋阶材料:虚数(丹恒•饮月 / 真理医生)", - "Stagnant_Shadow_Abomination": "角色晋阶材料:量子(玲可 / 符玄 / 雪衣)", - "Stagnant_Shadow_Scorch": "角色晋阶材料:火(桂乃芬 / 托帕&账账)", - "Stagnant_Shadow_Celestial": "角色晋阶材料:风(刃 / 藿藿)", "Stagnant_Shadow_Perdition": "角色晋阶材料:物理(寒鸦 / 银枝)", + "Stagnant_Shadow_Blaze": "角色晋阶材料:火(姬子 / 艾丝妲 / 虎克)", + "Stagnant_Shadow_Scorch": "角色晋阶材料:火(桂乃芬 / 托帕&账账)", + "Stagnant_Shadow_Rime": "角色晋阶材料:冰(三月七 / 黑塔 / 杰帕德 / 佩拉)", + "Stagnant_Shadow_Icicle": "角色晋阶材料:冰(彦卿 / 镜流 / 阮•梅)", + "Stagnant_Shadow_Nectar": "角色晋阶材料:冰(米沙)", + "Stagnant_Shadow_Fulmination": "角色晋阶材料:雷(阿兰 / 希露瓦 / 停云 / 白露)", + "Stagnant_Shadow_Doom": "角色晋阶材料:雷(卡芙卡 / 景元)", + "Stagnant_Shadow_Gust": "角色晋阶材料:风(丹恒 / 布洛妮娅 / 桑博)", + "Stagnant_Shadow_Celestial": "角色晋阶材料:风(刃 / 藿藿 / 黑天鹅)", + "Stagnant_Shadow_Quanta": "角色晋阶材料:量子(银狼 / 希儿 / 青雀)", + "Stagnant_Shadow_Abomination": "角色晋阶材料:量子(玲可 / 符玄 / 雪衣)", + "Stagnant_Shadow_Roast": "角色晋阶材料:量子(花火)", + "Stagnant_Shadow_Mirage": "角色晋阶材料:虚数(瓦尔特 / 罗刹 / 驭空)", + "Stagnant_Shadow_Puppetry": "角色晋阶材料:虚数(丹恒•饮月 / 真理医生)", "Cavern_of_Corrosion_Path_of_Gelid_Wind": "遗器:冰套+风套(霜风之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "遗器:物理套+击破套(迅拳之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Drifting": "遗器:治疗套+快枪手(漂泊之径•侵蚀隧洞)", @@ -278,22 +289,32 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "遗器:防御套+雷套(圣颂之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Conflagration": "遗器:火套+虚数套(野焰之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遗器:生命套+速度套(药使之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Darkness": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)" + "Cavern_of_Corrosion_Path_of_Darkness": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径•侵蚀隧洞)" }, "NameAtDoubleCalyx": { "name": "有双倍花活动时,选择副本", "help": "次数耗尽后回退到默认打本设置", "do_not_participate": "不参与活动", - "Calyx_Golden_Memories": "材料:角色经验(回忆之蕾•拟造花萼金)", - "Calyx_Golden_Aether": "材料:武器经验(以太之蕾•拟造花萼金)", - "Calyx_Golden_Treasures": "材料:信用点(藏珍之蕾•拟造花萼金)", - "Calyx_Crimson_Destruction": "行迹材料:毁灭(毁灭之蕾•拟造花萼赤)", - "Calyx_Crimson_Preservation": "行迹材料:存护(存护之蕾•拟造花萼赤)", - "Calyx_Crimson_The_Hunt": "行迹材料:巡猎(巡猎之蕾•拟造花萼赤)", - "Calyx_Crimson_Abundance": "行迹材料:丰饶(丰饶之蕾•拟造花萼赤)", - "Calyx_Crimson_Erudition": "行迹材料:智识(智识之蕾•拟造花萼赤)", - "Calyx_Crimson_Harmony": "行迹材料:同谐(同谐之蕾•拟造花萼赤)", - "Calyx_Crimson_Nihility": "行迹材料:虚无(虚无之蕾•拟造花萼赤)" + "Calyx_Golden_Memories_Jarilo_VI": "材料:角色经验(回忆之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "材料:角色经验(回忆之蕾•仙舟罗浮)", + "Calyx_Golden_Memories_Penacony": "材料:角色经验(回忆之蕾•匹诺康尼)", + "Calyx_Golden_Aether_Jarilo_VI": "材料:武器经验(以太之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "材料:武器经验(以太之蕾•仙舟罗浮)", + "Calyx_Golden_Aether_Penacony": "材料:武器经验(以太之蕾•匹诺康尼)", + "Calyx_Golden_Treasures_Jarilo_VI": "材料:信用点(藏珍之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "材料:信用点(藏珍之蕾•仙舟罗浮)", + "Calyx_Golden_Treasures_Penacony": "材料:信用点(藏珍之蕾•匹诺康尼)", + "Calyx_Crimson_Destruction_Herta_StorageZone": "行迹材料:毁灭(收容舱段)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "行迹材料:毁灭(鳞渊境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "行迹材料:存护(支援舱段)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "行迹材料:巡猎(城郊雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "行迹材料:丰饶(边缘通路)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "行迹材料:智识(铆钉镇)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "行迹材料:同谐(机械聚落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "行迹材料:同谐(白日梦酒店-梦境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "行迹材料:虚无(大矿区)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "行迹材料:虚无(丹鼎司)" }, "NameAtDoubleRelic": { "name": "有遗器活动时,选择副本", @@ -306,7 +327,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "遗器:防御套+雷套(圣颂之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Conflagration": "遗器:火套+虚数套(野焰之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遗器:生命套+速度套(药使之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Darkness": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)" + "Cavern_of_Corrosion_Path_of_Darkness": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径•侵蚀隧洞)" }, "Team": { "name": "打本队伍", @@ -331,40 +353,51 @@ "name": "完成1次拟造花萼(金)", "help": "", "do_not_achieve": "不完成这个任务", - "Calyx_Golden_Memories": "材料:角色经验(回忆之蕾•拟造花萼金)", - "Calyx_Golden_Aether": "材料:武器经验(以太之蕾•拟造花萼金)", - "Calyx_Golden_Treasures": "材料:信用点(藏珍之蕾•拟造花萼金)" + "Calyx_Golden_Memories_Jarilo_VI": "材料:角色经验(回忆之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "材料:角色经验(回忆之蕾•仙舟罗浮)", + "Calyx_Golden_Memories_Penacony": "材料:角色经验(回忆之蕾•匹诺康尼)", + "Calyx_Golden_Aether_Jarilo_VI": "材料:武器经验(以太之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "材料:武器经验(以太之蕾•仙舟罗浮)", + "Calyx_Golden_Aether_Penacony": "材料:武器经验(以太之蕾•匹诺康尼)", + "Calyx_Golden_Treasures_Jarilo_VI": "材料:信用点(藏珍之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "材料:信用点(藏珍之蕾•仙舟罗浮)", + "Calyx_Golden_Treasures_Penacony": "材料:信用点(藏珍之蕾•匹诺康尼)" }, "CalyxCrimson": { "name": "完成1次拟造花萼(赤)", "help": "", "do_not_achieve": "不完成这个任务", - "Calyx_Crimson_Destruction": "行迹材料:毁灭(毁灭之蕾•拟造花萼赤)", - "Calyx_Crimson_Preservation": "行迹材料:存护(存护之蕾•拟造花萼赤)", - "Calyx_Crimson_The_Hunt": "行迹材料:巡猎(巡猎之蕾•拟造花萼赤)", - "Calyx_Crimson_Abundance": "行迹材料:丰饶(丰饶之蕾•拟造花萼赤)", - "Calyx_Crimson_Erudition": "行迹材料:智识(智识之蕾•拟造花萼赤)", - "Calyx_Crimson_Harmony": "行迹材料:同谐(同谐之蕾•拟造花萼赤)", - "Calyx_Crimson_Nihility": "行迹材料:虚无(虚无之蕾•拟造花萼赤)" + "Calyx_Crimson_Destruction_Herta_StorageZone": "行迹材料:毁灭(收容舱段)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "行迹材料:毁灭(鳞渊境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "行迹材料:存护(支援舱段)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "行迹材料:巡猎(城郊雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "行迹材料:丰饶(边缘通路)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "行迹材料:智识(铆钉镇)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "行迹材料:同谐(机械聚落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "行迹材料:同谐(白日梦酒店-梦境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "行迹材料:虚无(大矿区)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "行迹材料:虚无(丹鼎司)" }, "StagnantShadow": { "name": "完成1次凝滞虚影", "help": "", "do_not_achieve": "不完成这个任务", - "Stagnant_Shadow_Quanta": "角色晋阶材料:量子(银狼 / 希儿 / 青雀)", - "Stagnant_Shadow_Gust": "角色晋阶材料:风(丹恒 / 布洛妮娅 / 桑博)", - "Stagnant_Shadow_Fulmination": "角色晋阶材料:雷(阿兰 / 希露瓦 / 停云 / 白露)", - "Stagnant_Shadow_Blaze": "角色晋阶材料:火(姬子 / 艾丝妲 / 虎克)", "Stagnant_Shadow_Spike": "角色晋阶材料:物理(娜塔莎 / 克拉拉 / 卢卡 / 素裳)", - "Stagnant_Shadow_Rime": "角色晋阶材料:冰(三月七 / 黑塔 / 杰帕德 / 佩拉)", - "Stagnant_Shadow_Mirage": "角色晋阶材料:虚数(瓦尔特 / 罗刹 / 驭空)", - "Stagnant_Shadow_Icicle": "角色晋阶材料:冰(彦卿 / 镜流 / 阮•梅)", - "Stagnant_Shadow_Doom": "角色晋阶材料:雷(卡芙卡 / 景元)", - "Stagnant_Shadow_Puppetry": "角色晋阶材料:虚数(丹恒•饮月 / 真理医生)", - "Stagnant_Shadow_Abomination": "角色晋阶材料:量子(玲可 / 符玄 / 雪衣)", + "Stagnant_Shadow_Perdition": "角色晋阶材料:物理(寒鸦 / 银枝)", + "Stagnant_Shadow_Blaze": "角色晋阶材料:火(姬子 / 艾丝妲 / 虎克)", "Stagnant_Shadow_Scorch": "角色晋阶材料:火(桂乃芬 / 托帕&账账)", - "Stagnant_Shadow_Celestial": "角色晋阶材料:风(刃 / 藿藿)", - "Stagnant_Shadow_Perdition": "角色晋阶材料:物理(寒鸦 / 银枝)" + "Stagnant_Shadow_Rime": "角色晋阶材料:冰(三月七 / 黑塔 / 杰帕德 / 佩拉)", + "Stagnant_Shadow_Icicle": "角色晋阶材料:冰(彦卿 / 镜流 / 阮•梅)", + "Stagnant_Shadow_Nectar": "角色晋阶材料:冰(米沙)", + "Stagnant_Shadow_Fulmination": "角色晋阶材料:雷(阿兰 / 希露瓦 / 停云 / 白露)", + "Stagnant_Shadow_Doom": "角色晋阶材料:雷(卡芙卡 / 景元)", + "Stagnant_Shadow_Gust": "角色晋阶材料:风(丹恒 / 布洛妮娅 / 桑博)", + "Stagnant_Shadow_Celestial": "角色晋阶材料:风(刃 / 藿藿 / 黑天鹅)", + "Stagnant_Shadow_Quanta": "角色晋阶材料:量子(银狼 / 希儿 / 青雀)", + "Stagnant_Shadow_Abomination": "角色晋阶材料:量子(玲可 / 符玄 / 雪衣)", + "Stagnant_Shadow_Roast": "角色晋阶材料:量子(花火)", + "Stagnant_Shadow_Mirage": "角色晋阶材料:虚数(瓦尔特 / 罗刹 / 驭空)", + "Stagnant_Shadow_Puppetry": "角色晋阶材料:虚数(丹恒•饮月 / 真理医生)" }, "CavernOfCorrosion": { "name": "完成1次侵蚀隧洞", @@ -377,7 +410,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "遗器:防御套+雷套(圣颂之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Conflagration": "遗器:火套+虚数套(野焰之径•侵蚀隧洞)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遗器:生命套+速度套(药使之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Darkness": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)" + "Cavern_of_Corrosion_Path_of_Darkness": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径•侵蚀隧洞)" } }, "DungeonSupport": { @@ -394,17 +428,19 @@ }, "Character": { "name": "好友支援角色", - "help": "选择好友支援角色,未找到则选择默认(第一个)角色", + "help": "选择好友支援角色,未找到则选择默认(第一个)角色\n支援角色不要与队伍中的角色重复,建议置顶好友角色", "FirstCharacter": "支援列表第一个角色", "Argenti": "银枝", "Arlan": "阿兰", "Asta": "艾丝妲", "Bailu": "白露", + "BlackSwan": "黑天鹅", "Blade": "刃", "Bronya": "布洛妮娅", "Clara": "克拉拉", "DanHeng": "丹恒", "DanHengImbibitorLunae": "丹恒•饮月", + "DrRatio": "真理医生", "FuXuan": "符玄", "Gepard": "杰帕德", "Guinaifen": "桂乃芬", @@ -420,6 +456,7 @@ "Luocha": "罗刹", "Lynx": "玲可", "March7th": "三月七", + "Misha": "米沙", "Natasha": "娜塔莎", "Pela": "佩拉", "Qingque": "青雀", @@ -428,6 +465,7 @@ "Seele": "希儿", "Serval": "希露瓦", "SilverWolf": "银狼", + "Sparkle": "花火", "Sushang": "素裳", "Tingyun": "停云", "TopazNumby": "托帕&账账", @@ -760,15 +798,19 @@ "Born_to_Obey": "古代零件(生而服从)", "Root_Out_the_Turpitude": "永寿幼芽(根除恶孽)", "Fire_Lord_Inflames_Blades_of_War": "工造机杼(火帝动炉销剑戟)", + "A_Startling_Night_Terror": "蓄梦元件(劫梦惊魂)", + "Tranquility_of_Vimala_bhumi": "思绪末屑(离垢清净)", "Nameless_Land_Nameless_People": "角色经验材料(无名之地,无名之人)", - "Akashic_Records": "光锥强化材料(阿卡夏记录)", + "Akashic_Records": "光锥经验材料(阿卡夏记录)", "The_Invisible_Hand": "信用点(看不见的手)", - "Abandoned_and_Insulted": "燃素&金属(被废弃与损害的)", - "Spring_of_Life": "虚粒子&固态净水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黄金大地)", - "The_Blossom_in_the_Storm": "气态流体&种子(风暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆单元&废弃机巧零件(偃师传说)", - "The_Wages_of_Humanity": "药草提取物&一人嘉禾(赡养人类)" + "Abandoned_and_Insulted": "燃素 & 金属(被废弃与损害的)", + "Spring_of_Life": "固态净水 & 虚粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黄金大地)", + "The_Blossom_in_the_Storm": "气态流体 & 种子(风暴中怒放的花)", + "Legend_of_the_Puppet_Master": "废弃机巧零件 & 玉兆单元(偃师传说)", + "The_Wages_of_Humanity": "一人嘉禾 & 药草提取物(赡养人类)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎梦(幻梦的残片)", + "Scalpel_and_Screwdriver": "锈迹齿轮 & 老旧臼齿(手术刀与螺丝刀)" }, "Name_2": { "name": "第2个委托选择", @@ -779,15 +821,19 @@ "Born_to_Obey": "古代零件(生而服从)", "Root_Out_the_Turpitude": "永寿幼芽(根除恶孽)", "Fire_Lord_Inflames_Blades_of_War": "工造机杼(火帝动炉销剑戟)", + "A_Startling_Night_Terror": "蓄梦元件(劫梦惊魂)", + "Tranquility_of_Vimala_bhumi": "思绪末屑(离垢清净)", "Nameless_Land_Nameless_People": "角色经验材料(无名之地,无名之人)", - "Akashic_Records": "光锥强化材料(阿卡夏记录)", + "Akashic_Records": "光锥经验材料(阿卡夏记录)", "The_Invisible_Hand": "信用点(看不见的手)", - "Abandoned_and_Insulted": "燃素&金属(被废弃与损害的)", - "Spring_of_Life": "虚粒子&固态净水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黄金大地)", - "The_Blossom_in_the_Storm": "气态流体&种子(风暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆单元&废弃机巧零件(偃师传说)", - "The_Wages_of_Humanity": "药草提取物&一人嘉禾(赡养人类)" + "Abandoned_and_Insulted": "燃素 & 金属(被废弃与损害的)", + "Spring_of_Life": "固态净水 & 虚粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黄金大地)", + "The_Blossom_in_the_Storm": "气态流体 & 种子(风暴中怒放的花)", + "Legend_of_the_Puppet_Master": "废弃机巧零件 & 玉兆单元(偃师传说)", + "The_Wages_of_Humanity": "一人嘉禾 & 药草提取物(赡养人类)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎梦(幻梦的残片)", + "Scalpel_and_Screwdriver": "锈迹齿轮 & 老旧臼齿(手术刀与螺丝刀)" }, "Name_3": { "name": "第3个委托选择", @@ -798,15 +844,19 @@ "Born_to_Obey": "古代零件(生而服从)", "Root_Out_the_Turpitude": "永寿幼芽(根除恶孽)", "Fire_Lord_Inflames_Blades_of_War": "工造机杼(火帝动炉销剑戟)", + "A_Startling_Night_Terror": "蓄梦元件(劫梦惊魂)", + "Tranquility_of_Vimala_bhumi": "思绪末屑(离垢清净)", "Nameless_Land_Nameless_People": "角色经验材料(无名之地,无名之人)", - "Akashic_Records": "光锥强化材料(阿卡夏记录)", + "Akashic_Records": "光锥经验材料(阿卡夏记录)", "The_Invisible_Hand": "信用点(看不见的手)", - "Abandoned_and_Insulted": "燃素&金属(被废弃与损害的)", - "Spring_of_Life": "虚粒子&固态净水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黄金大地)", - "The_Blossom_in_the_Storm": "气态流体&种子(风暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆单元&废弃机巧零件(偃师传说)", - "The_Wages_of_Humanity": "药草提取物&一人嘉禾(赡养人类)" + "Abandoned_and_Insulted": "燃素 & 金属(被废弃与损害的)", + "Spring_of_Life": "固态净水 & 虚粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黄金大地)", + "The_Blossom_in_the_Storm": "气态流体 & 种子(风暴中怒放的花)", + "Legend_of_the_Puppet_Master": "废弃机巧零件 & 玉兆单元(偃师传说)", + "The_Wages_of_Humanity": "一人嘉禾 & 药草提取物(赡养人类)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎梦(幻梦的残片)", + "Scalpel_and_Screwdriver": "锈迹齿轮 & 老旧臼齿(手术刀与螺丝刀)" }, "Name_4": { "name": "第4个委托选择", @@ -817,15 +867,19 @@ "Born_to_Obey": "古代零件(生而服从)", "Root_Out_the_Turpitude": "永寿幼芽(根除恶孽)", "Fire_Lord_Inflames_Blades_of_War": "工造机杼(火帝动炉销剑戟)", + "A_Startling_Night_Terror": "蓄梦元件(劫梦惊魂)", + "Tranquility_of_Vimala_bhumi": "思绪末屑(离垢清净)", "Nameless_Land_Nameless_People": "角色经验材料(无名之地,无名之人)", - "Akashic_Records": "光锥强化材料(阿卡夏记录)", + "Akashic_Records": "光锥经验材料(阿卡夏记录)", "The_Invisible_Hand": "信用点(看不见的手)", - "Abandoned_and_Insulted": "燃素&金属(被废弃与损害的)", - "Spring_of_Life": "虚粒子&固态净水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黄金大地)", - "The_Blossom_in_the_Storm": "气态流体&种子(风暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆单元&废弃机巧零件(偃师传说)", - "The_Wages_of_Humanity": "药草提取物&一人嘉禾(赡养人类)" + "Abandoned_and_Insulted": "燃素 & 金属(被废弃与损害的)", + "Spring_of_Life": "固态净水 & 虚粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黄金大地)", + "The_Blossom_in_the_Storm": "气态流体 & 种子(风暴中怒放的花)", + "Legend_of_the_Puppet_Master": "废弃机巧零件 & 玉兆单元(偃师传说)", + "The_Wages_of_Humanity": "一人嘉禾 & 药草提取物(赡养人类)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎梦(幻梦的残片)", + "Scalpel_and_Screwdriver": "锈迹齿轮 & 老旧臼齿(手术刀与螺丝刀)" }, "Duration": { "name": "派遣时长", @@ -974,6 +1028,14 @@ "name": "剧情连点器", "help": "监听画面自动点击剧情、手机聊天、模拟宇宙祝福(遵循模拟宇宙任务设置)", "True": "已启用" + }, + "AimClicker": { + "name": "点击被瞄准破坏物和敌人", + "help": "", + "item_enemy": "点击破坏物和敌人", + "item": "仅点击破坏物", + "enemy": "仅点击敌人", + "do_not_click": "不点击" } }, "Gui": { diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 043b7cdbc..1919db4de 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -247,30 +247,41 @@ "Name": { "name": "副本名稱", "help": "默認打本設定", - "Calyx_Golden_Memories": "材料:角色經驗(回憶之蕾•擬造花萼金)", - "Calyx_Golden_Aether": "材料:武器經驗(乙太之蕾•擬造花萼金)", - "Calyx_Golden_Treasures": "材料:信用點(藏珍之蕾•擬造花萼金)", - "Calyx_Crimson_Destruction": "行跡材料:毀滅(毀滅之蕾•擬造花萼赤)", - "Calyx_Crimson_Preservation": "行跡材料:存護(存護之蕾•擬造花萼赤)", - "Calyx_Crimson_The_Hunt": "行跡材料:巡獵(巡獵之蕾•擬造花萼赤)", - "Calyx_Crimson_Abundance": "行跡材料:豐饒(豐饒之蕾•擬造花萼赤)", - "Calyx_Crimson_Erudition": "行跡材料:智識(智識之蕾•擬造花萼赤)", - "Calyx_Crimson_Harmony": "行跡材料:同諧(同諧之蕾•擬造花萼赤)", - "Calyx_Crimson_Nihility": "行跡材料:虛無(虛無之蕾•擬造花萼赤)", - "Stagnant_Shadow_Quanta": "角色晉階材料:量子(銀狼 / 希兒 / 青雀)", - "Stagnant_Shadow_Gust": "角色晉階材料:風(丹恆 / 布洛妮婭 / 桑博)", - "Stagnant_Shadow_Fulmination": "角色晉階材料:雷(阿蘭 / 希露瓦 / 停雲 / 白露)", - "Stagnant_Shadow_Blaze": "角色晉階材料:火(姬子 / 艾絲妲 / 虎克)", + "Calyx_Golden_Memories_Jarilo_VI": "材料:角色經驗(回憶之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "材料:角色經驗(回憶之蕾•仙舟羅浮)", + "Calyx_Golden_Memories_Penacony": "材料:角色經驗(回憶之蕾•匹諾康尼)", + "Calyx_Golden_Aether_Jarilo_VI": "材料:武器經驗(乙太之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "材料:武器經驗(乙太之蕾•仙舟羅浮)", + "Calyx_Golden_Aether_Penacony": "材料:武器經驗(乙太之蕾•匹諾康尼)", + "Calyx_Golden_Treasures_Jarilo_VI": "材料:信用點(藏珍之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "材料:信用點(藏珍之蕾•仙舟羅浮)", + "Calyx_Golden_Treasures_Penacony": "材料:信用點(藏珍之蕾•匹諾康尼)", + "Calyx_Crimson_Destruction_Herta_StorageZone": "行跡材料:毀滅(收容艙段)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "行跡材料:毀滅(鱗淵境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "行跡材料:存護(支援艙段)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "行跡材料:巡獵(城郊雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "行跡材料:豐饒(邊緣通道)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "行跡材料:智識(鉚釘鎮)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "行跡材料:同諧(機械聚落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "行跡材料:同諧(白日夢飯店-夢境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "行跡材料:虛無(大礦區)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "行跡材料:虛無(丹鼎司)", "Stagnant_Shadow_Spike": "角色晉階材料:物理(娜塔莎 / 克拉拉 / 盧卡 / 素裳)", - "Stagnant_Shadow_Rime": "角色晉階材料:冰(三月七 / 黑塔 / 傑帕德 / 佩拉)", - "Stagnant_Shadow_Mirage": "角色晉階材料:虛數(瓦爾特 / 羅剎 / 馭空)", - "Stagnant_Shadow_Icicle": "角色晉階材料:冰(彥卿 / 鏡流 / 阮•梅)", - "Stagnant_Shadow_Doom": "角色晉階材料:雷(卡芙卡 / 景元)", - "Stagnant_Shadow_Puppetry": "角色晉階材料:虛數(丹恆•飲月 / 真理醫生)", - "Stagnant_Shadow_Abomination": "角色晉階材料:量子(玲可 / 符玄 / 雪衣)", - "Stagnant_Shadow_Scorch": "角色晉階材料:火(桂乃芬 / 托帕&帳帳)", - "Stagnant_Shadow_Celestial": "角色晉階材料:風(刃 / 藿藿)", "Stagnant_Shadow_Perdition": "角色晉階材料:物理(寒鴉 / 銀枝)", + "Stagnant_Shadow_Blaze": "角色晉階材料:火(姬子 / 艾絲妲 / 虎克)", + "Stagnant_Shadow_Scorch": "角色晉階材料:火(桂乃芬 / 托帕&帳帳)", + "Stagnant_Shadow_Rime": "角色晉階材料:冰(三月七 / 黑塔 / 傑帕德 / 佩拉)", + "Stagnant_Shadow_Icicle": "角色晉階材料:冰(彥卿 / 鏡流 / 阮•梅)", + "Stagnant_Shadow_Nectar": "角色晉階材料:冰(米沙)", + "Stagnant_Shadow_Fulmination": "角色晉階材料:雷(阿蘭 / 希露瓦 / 停雲 / 白露)", + "Stagnant_Shadow_Doom": "角色晉階材料:雷(卡芙卡 / 景元)", + "Stagnant_Shadow_Gust": "角色晉階材料:風(丹恆 / 布洛妮婭 / 桑博)", + "Stagnant_Shadow_Celestial": "角色晉階材料:風(刃 / 藿藿 / 黑天鵝)", + "Stagnant_Shadow_Quanta": "角色晉階材料:量子(銀狼 / 希兒 / 青雀)", + "Stagnant_Shadow_Abomination": "角色晉階材料:量子(玲可 / 符玄 / 雪衣)", + "Stagnant_Shadow_Roast": "角色晉階材料:量子(花火)", + "Stagnant_Shadow_Mirage": "角色晉階材料:虛數(瓦爾特 / 羅剎 / 馭空)", + "Stagnant_Shadow_Puppetry": "角色晉階材料:虛數(丹恆•飲月 / 真理醫生)", "Cavern_of_Corrosion_Path_of_Gelid_Wind": "遺器:冰套+風套(霜風之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Jabbing_Punch": "遺器:物理套+擊破套(迅拳之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Drifting": "遺器:治療套+快槍手(漂泊之徑•侵蝕隧洞)", @@ -278,22 +289,32 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "遺器:防禦套+雷套(聖頌之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Conflagration": "遺器:火套+虛數套(野焰之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遺器:生命套+速度套(藥使之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Darkness": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)" + "Cavern_of_Corrosion_Path_of_Darkness": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套(夢潛之徑•侵蝕隧洞)" }, "NameAtDoubleCalyx": { "name": "有雙倍花活動時,選擇副本", "help": "次數耗儘後回退到默認打本設定", "do_not_participate": "不參與活動", - "Calyx_Golden_Memories": "材料:角色經驗(回憶之蕾•擬造花萼金)", - "Calyx_Golden_Aether": "材料:武器經驗(乙太之蕾•擬造花萼金)", - "Calyx_Golden_Treasures": "材料:信用點(藏珍之蕾•擬造花萼金)", - "Calyx_Crimson_Destruction": "行跡材料:毀滅(毀滅之蕾•擬造花萼赤)", - "Calyx_Crimson_Preservation": "行跡材料:存護(存護之蕾•擬造花萼赤)", - "Calyx_Crimson_The_Hunt": "行跡材料:巡獵(巡獵之蕾•擬造花萼赤)", - "Calyx_Crimson_Abundance": "行跡材料:豐饒(豐饒之蕾•擬造花萼赤)", - "Calyx_Crimson_Erudition": "行跡材料:智識(智識之蕾•擬造花萼赤)", - "Calyx_Crimson_Harmony": "行跡材料:同諧(同諧之蕾•擬造花萼赤)", - "Calyx_Crimson_Nihility": "行跡材料:虛無(虛無之蕾•擬造花萼赤)" + "Calyx_Golden_Memories_Jarilo_VI": "材料:角色經驗(回憶之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "材料:角色經驗(回憶之蕾•仙舟羅浮)", + "Calyx_Golden_Memories_Penacony": "材料:角色經驗(回憶之蕾•匹諾康尼)", + "Calyx_Golden_Aether_Jarilo_VI": "材料:武器經驗(乙太之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "材料:武器經驗(乙太之蕾•仙舟羅浮)", + "Calyx_Golden_Aether_Penacony": "材料:武器經驗(乙太之蕾•匹諾康尼)", + "Calyx_Golden_Treasures_Jarilo_VI": "材料:信用點(藏珍之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "材料:信用點(藏珍之蕾•仙舟羅浮)", + "Calyx_Golden_Treasures_Penacony": "材料:信用點(藏珍之蕾•匹諾康尼)", + "Calyx_Crimson_Destruction_Herta_StorageZone": "行跡材料:毀滅(收容艙段)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "行跡材料:毀滅(鱗淵境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "行跡材料:存護(支援艙段)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "行跡材料:巡獵(城郊雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "行跡材料:豐饒(邊緣通道)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "行跡材料:智識(鉚釘鎮)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "行跡材料:同諧(機械聚落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "行跡材料:同諧(白日夢飯店-夢境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "行跡材料:虛無(大礦區)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "行跡材料:虛無(丹鼎司)" }, "NameAtDoubleRelic": { "name": "有遺器活動時,選擇副本", @@ -306,7 +327,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "遺器:防禦套+雷套(聖頌之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Conflagration": "遺器:火套+虛數套(野焰之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遺器:生命套+速度套(藥使之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Darkness": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)" + "Cavern_of_Corrosion_Path_of_Darkness": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套(夢潛之徑•侵蝕隧洞)" }, "Team": { "name": "打本隊伍", @@ -331,40 +353,51 @@ "name": "完成1次擬造花萼(金)", "help": "", "do_not_achieve": "不完成這個任務", - "Calyx_Golden_Memories": "材料:角色經驗(回憶之蕾•擬造花萼金)", - "Calyx_Golden_Aether": "材料:武器經驗(乙太之蕾•擬造花萼金)", - "Calyx_Golden_Treasures": "材料:信用點(藏珍之蕾•擬造花萼金)" + "Calyx_Golden_Memories_Jarilo_VI": "材料:角色經驗(回憶之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "材料:角色經驗(回憶之蕾•仙舟羅浮)", + "Calyx_Golden_Memories_Penacony": "材料:角色經驗(回憶之蕾•匹諾康尼)", + "Calyx_Golden_Aether_Jarilo_VI": "材料:武器經驗(乙太之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "材料:武器經驗(乙太之蕾•仙舟羅浮)", + "Calyx_Golden_Aether_Penacony": "材料:武器經驗(乙太之蕾•匹諾康尼)", + "Calyx_Golden_Treasures_Jarilo_VI": "材料:信用點(藏珍之蕾•雅利洛-Ⅵ)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "材料:信用點(藏珍之蕾•仙舟羅浮)", + "Calyx_Golden_Treasures_Penacony": "材料:信用點(藏珍之蕾•匹諾康尼)" }, "CalyxCrimson": { "name": "完成1次擬造花萼(赤)", "help": "", "do_not_achieve": "不完成這個任務", - "Calyx_Crimson_Destruction": "行跡材料:毀滅(毀滅之蕾•擬造花萼赤)", - "Calyx_Crimson_Preservation": "行跡材料:存護(存護之蕾•擬造花萼赤)", - "Calyx_Crimson_The_Hunt": "行跡材料:巡獵(巡獵之蕾•擬造花萼赤)", - "Calyx_Crimson_Abundance": "行跡材料:豐饒(豐饒之蕾•擬造花萼赤)", - "Calyx_Crimson_Erudition": "行跡材料:智識(智識之蕾•擬造花萼赤)", - "Calyx_Crimson_Harmony": "行跡材料:同諧(同諧之蕾•擬造花萼赤)", - "Calyx_Crimson_Nihility": "行跡材料:虛無(虛無之蕾•擬造花萼赤)" + "Calyx_Crimson_Destruction_Herta_StorageZone": "行跡材料:毀滅(收容艙段)", + "Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape": "行跡材料:毀滅(鱗淵境)", + "Calyx_Crimson_Preservation_Herta_SupplyZone": "行跡材料:存護(支援艙段)", + "Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains": "行跡材料:巡獵(城郊雪原)", + "Calyx_Crimson_Abundance_Jarilo_BackwaterPass": "行跡材料:豐饒(邊緣通道)", + "Calyx_Crimson_Erudition_Jarilo_RivetTown": "行跡材料:智識(鉚釘鎮)", + "Calyx_Crimson_Harmony_Jarilo_RobotSettlement": "行跡材料:同諧(機械聚落)", + "Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape": "行跡材料:同諧(白日夢飯店-夢境)", + "Calyx_Crimson_Nihility_Jarilo_GreatMine": "行跡材料:虛無(大礦區)", + "Calyx_Crimson_Nihility_Luofu_AlchemyCommission": "行跡材料:虛無(丹鼎司)" }, "StagnantShadow": { "name": "完成1次凝滯虛影", "help": "", "do_not_achieve": "不完成這個任務", - "Stagnant_Shadow_Quanta": "角色晉階材料:量子(銀狼 / 希兒 / 青雀)", - "Stagnant_Shadow_Gust": "角色晉階材料:風(丹恆 / 布洛妮婭 / 桑博)", - "Stagnant_Shadow_Fulmination": "角色晉階材料:雷(阿蘭 / 希露瓦 / 停雲 / 白露)", - "Stagnant_Shadow_Blaze": "角色晉階材料:火(姬子 / 艾絲妲 / 虎克)", "Stagnant_Shadow_Spike": "角色晉階材料:物理(娜塔莎 / 克拉拉 / 盧卡 / 素裳)", - "Stagnant_Shadow_Rime": "角色晉階材料:冰(三月七 / 黑塔 / 傑帕德 / 佩拉)", - "Stagnant_Shadow_Mirage": "角色晉階材料:虛數(瓦爾特 / 羅剎 / 馭空)", - "Stagnant_Shadow_Icicle": "角色晉階材料:冰(彥卿 / 鏡流 / 阮•梅)", - "Stagnant_Shadow_Doom": "角色晉階材料:雷(卡芙卡 / 景元)", - "Stagnant_Shadow_Puppetry": "角色晉階材料:虛數(丹恆•飲月 / 真理醫生)", - "Stagnant_Shadow_Abomination": "角色晉階材料:量子(玲可 / 符玄 / 雪衣)", + "Stagnant_Shadow_Perdition": "角色晉階材料:物理(寒鴉 / 銀枝)", + "Stagnant_Shadow_Blaze": "角色晉階材料:火(姬子 / 艾絲妲 / 虎克)", "Stagnant_Shadow_Scorch": "角色晉階材料:火(桂乃芬 / 托帕&帳帳)", - "Stagnant_Shadow_Celestial": "角色晉階材料:風(刃 / 藿藿)", - "Stagnant_Shadow_Perdition": "角色晉階材料:物理(寒鴉 / 銀枝)" + "Stagnant_Shadow_Rime": "角色晉階材料:冰(三月七 / 黑塔 / 傑帕德 / 佩拉)", + "Stagnant_Shadow_Icicle": "角色晉階材料:冰(彥卿 / 鏡流 / 阮•梅)", + "Stagnant_Shadow_Nectar": "角色晉階材料:冰(米沙)", + "Stagnant_Shadow_Fulmination": "角色晉階材料:雷(阿蘭 / 希露瓦 / 停雲 / 白露)", + "Stagnant_Shadow_Doom": "角色晉階材料:雷(卡芙卡 / 景元)", + "Stagnant_Shadow_Gust": "角色晉階材料:風(丹恆 / 布洛妮婭 / 桑博)", + "Stagnant_Shadow_Celestial": "角色晉階材料:風(刃 / 藿藿 / 黑天鵝)", + "Stagnant_Shadow_Quanta": "角色晉階材料:量子(銀狼 / 希兒 / 青雀)", + "Stagnant_Shadow_Abomination": "角色晉階材料:量子(玲可 / 符玄 / 雪衣)", + "Stagnant_Shadow_Roast": "角色晉階材料:量子(花火)", + "Stagnant_Shadow_Mirage": "角色晉階材料:虛數(瓦爾特 / 羅剎 / 馭空)", + "Stagnant_Shadow_Puppetry": "角色晉階材料:虛數(丹恆•飲月 / 真理醫生)" }, "CavernOfCorrosion": { "name": "完成1次侵蝕隧洞", @@ -377,7 +410,8 @@ "Cavern_of_Corrosion_Path_of_Holy_Hymn": "遺器:防禦套+雷套(聖頌之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Conflagration": "遺器:火套+虛數套(野焰之徑•侵蝕隧洞)", "Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遺器:生命套+速度套(藥使之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Darkness": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)" + "Cavern_of_Corrosion_Path_of_Darkness": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套(夢潛之徑•侵蝕隧洞)" } }, "DungeonSupport": { @@ -394,17 +428,19 @@ }, "Character": { "name": "好友支援角色", - "help": "選擇好友支援角色,未找到則選擇默認(第一個)角色", + "help": "選擇好友支援角色,未找到則選擇默認(第一個)角色\n支援角色不要與隊伍中的角色重複,建議置頂好友角色", "FirstCharacter": "支援列表第一個角色", "Argenti": "銀枝", "Arlan": "阿蘭", "Asta": "艾絲妲", "Bailu": "白露", + "BlackSwan": "黑天鵝", "Blade": "刃", "Bronya": "布洛妮婭", "Clara": "克拉拉", "DanHeng": "丹恆", "DanHengImbibitorLunae": "丹恆•飲月", + "DrRatio": "真理醫生", "FuXuan": "符玄", "Gepard": "傑帕德", "Guinaifen": "桂乃芬", @@ -420,6 +456,7 @@ "Luocha": "羅剎", "Lynx": "玲可", "March7th": "三月七", + "Misha": "米沙", "Natasha": "娜塔莎", "Pela": "佩拉", "Qingque": "青雀", @@ -428,6 +465,7 @@ "Seele": "希兒", "Serval": "希露瓦", "SilverWolf": "銀狼", + "Sparkle": "花火", "Sushang": "素裳", "Tingyun": "停雲", "TopazNumby": "托帕&帳帳", @@ -760,15 +798,19 @@ "Born_to_Obey": "古代零件(生而服從)", "Root_Out_the_Turpitude": "永壽幼芽(根除惡孽)", "Fire_Lord_Inflames_Blades_of_War": "工造機杼(火帝動爐銷劍戟)", - "Nameless_Land_Nameless_People": "角色經驗材料(無名之地,無名之人)", - "Akashic_Records": "光錐強化材料(阿卡夏記錄)", + "A_Startling_Night_Terror": "蓄夢元件(劫夢驚魂)", + "Tranquility_of_Vimala_bhumi": "思緒末屑(離垢清淨)", + "Nameless_Land_Nameless_People": "角色經驗素材(無名之地,無名之人)", + "Akashic_Records": "光錐經驗素材(阿卡夏紀錄)", "The_Invisible_Hand": "信用點(看不見的手)", - "Abandoned_and_Insulted": "燃素&金屬(被廢棄與損害的)", - "Spring_of_Life": "虛粒子&固態淨水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黃金大地)", - "The_Blossom_in_the_Storm": "氣態流體&種子(風暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆單元&廢棄機巧零件(偃師傳說)", - "The_Wages_of_Humanity": "藥草萃取物&一人嘉禾(贍養人類)" + "Abandoned_and_Insulted": "燃素 & 金屬(被廢棄與損害的)", + "Spring_of_Life": "固態淨水 & 虛粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黃金大地)", + "The_Blossom_in_the_Storm": "氣態流體 & 種子(風暴中怒放的花)", + "Legend_of_the_Puppet_Master": "廢棄機巧零件 & 玉兆單元(偃師傳說)", + "The_Wages_of_Humanity": "一人嘉禾 & 藥草萃取物(贍養人類)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎夢(幻夢的殘片)", + "Scalpel_and_Screwdriver": "鏽跡齒輪 & 老舊臼齒(手術刀與螺絲起子)" }, "Name_2": { "name": "第2個委託選擇", @@ -779,15 +821,19 @@ "Born_to_Obey": "古代零件(生而服從)", "Root_Out_the_Turpitude": "永壽幼芽(根除惡孽)", "Fire_Lord_Inflames_Blades_of_War": "工造機杼(火帝動爐銷劍戟)", - "Nameless_Land_Nameless_People": "角色經驗材料(無名之地,無名之人)", - "Akashic_Records": "光錐強化材料(阿卡夏記錄)", + "A_Startling_Night_Terror": "蓄夢元件(劫夢驚魂)", + "Tranquility_of_Vimala_bhumi": "思緒末屑(離垢清淨)", + "Nameless_Land_Nameless_People": "角色經驗素材(無名之地,無名之人)", + "Akashic_Records": "光錐經驗素材(阿卡夏紀錄)", "The_Invisible_Hand": "信用點(看不見的手)", - "Abandoned_and_Insulted": "燃素&金屬(被廢棄與損害的)", - "Spring_of_Life": "虛粒子&固態淨水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黃金大地)", - "The_Blossom_in_the_Storm": "氣態流體&種子(風暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆單元&廢棄機巧零件(偃師傳說)", - "The_Wages_of_Humanity": "藥草萃取物&一人嘉禾(贍養人類)" + "Abandoned_and_Insulted": "燃素 & 金屬(被廢棄與損害的)", + "Spring_of_Life": "固態淨水 & 虛粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黃金大地)", + "The_Blossom_in_the_Storm": "氣態流體 & 種子(風暴中怒放的花)", + "Legend_of_the_Puppet_Master": "廢棄機巧零件 & 玉兆單元(偃師傳說)", + "The_Wages_of_Humanity": "一人嘉禾 & 藥草萃取物(贍養人類)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎夢(幻夢的殘片)", + "Scalpel_and_Screwdriver": "鏽跡齒輪 & 老舊臼齒(手術刀與螺絲起子)" }, "Name_3": { "name": "第3個委託選擇", @@ -798,15 +844,19 @@ "Born_to_Obey": "古代零件(生而服從)", "Root_Out_the_Turpitude": "永壽幼芽(根除惡孽)", "Fire_Lord_Inflames_Blades_of_War": "工造機杼(火帝動爐銷劍戟)", - "Nameless_Land_Nameless_People": "角色經驗材料(無名之地,無名之人)", - "Akashic_Records": "光錐強化材料(阿卡夏記錄)", + "A_Startling_Night_Terror": "蓄夢元件(劫夢驚魂)", + "Tranquility_of_Vimala_bhumi": "思緒末屑(離垢清淨)", + "Nameless_Land_Nameless_People": "角色經驗素材(無名之地,無名之人)", + "Akashic_Records": "光錐經驗素材(阿卡夏紀錄)", "The_Invisible_Hand": "信用點(看不見的手)", - "Abandoned_and_Insulted": "燃素&金屬(被廢棄與損害的)", - "Spring_of_Life": "虛粒子&固態淨水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黃金大地)", - "The_Blossom_in_the_Storm": "氣態流體&種子(風暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆單元&廢棄機巧零件(偃師傳說)", - "The_Wages_of_Humanity": "藥草萃取物&一人嘉禾(贍養人類)" + "Abandoned_and_Insulted": "燃素 & 金屬(被廢棄與損害的)", + "Spring_of_Life": "固態淨水 & 虛粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黃金大地)", + "The_Blossom_in_the_Storm": "氣態流體 & 種子(風暴中怒放的花)", + "Legend_of_the_Puppet_Master": "廢棄機巧零件 & 玉兆單元(偃師傳說)", + "The_Wages_of_Humanity": "一人嘉禾 & 藥草萃取物(贍養人類)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎夢(幻夢的殘片)", + "Scalpel_and_Screwdriver": "鏽跡齒輪 & 老舊臼齒(手術刀與螺絲起子)" }, "Name_4": { "name": "第4個委託選擇", @@ -817,15 +867,19 @@ "Born_to_Obey": "古代零件(生而服從)", "Root_Out_the_Turpitude": "永壽幼芽(根除惡孽)", "Fire_Lord_Inflames_Blades_of_War": "工造機杼(火帝動爐銷劍戟)", - "Nameless_Land_Nameless_People": "角色經驗材料(無名之地,無名之人)", - "Akashic_Records": "光錐強化材料(阿卡夏記錄)", + "A_Startling_Night_Terror": "蓄夢元件(劫夢驚魂)", + "Tranquility_of_Vimala_bhumi": "思緒末屑(離垢清淨)", + "Nameless_Land_Nameless_People": "角色經驗素材(無名之地,無名之人)", + "Akashic_Records": "光錐經驗素材(阿卡夏紀錄)", "The_Invisible_Hand": "信用點(看不見的手)", - "Abandoned_and_Insulted": "燃素&金屬(被廢棄與損害的)", - "Spring_of_Life": "虛粒子&固態淨水(生命之泉)", - "The_Land_of_Gold": "蛋白米&基本食材(黃金大地)", - "The_Blossom_in_the_Storm": "氣態流體&種子(風暴中怒放的花)", - "Legend_of_the_Puppet_Master": "玉兆單元&廢棄機巧零件(偃師傳說)", - "The_Wages_of_Humanity": "藥草萃取物&一人嘉禾(贍養人類)" + "Abandoned_and_Insulted": "燃素 & 金屬(被廢棄與損害的)", + "Spring_of_Life": "固態淨水 & 虛粒子(生命之泉)", + "The_Land_of_Gold": "基本食材 & 蛋白米(黃金大地)", + "The_Blossom_in_the_Storm": "氣態流體 & 種子(風暴中怒放的花)", + "Legend_of_the_Puppet_Master": "廢棄機巧零件 & 玉兆單元(偃師傳說)", + "The_Wages_of_Humanity": "一人嘉禾 & 藥草萃取物(贍養人類)", + "Fragments_of_Illusory_Dreams": "安逸 & 碎夢(幻夢的殘片)", + "Scalpel_and_Screwdriver": "鏽跡齒輪 & 老舊臼齒(手術刀與螺絲起子)" }, "Duration": { "name": "派遣時間", @@ -974,6 +1028,14 @@ "name": "劇情連點器", "help": "監聽畫面自動點擊劇情、手機聊天、模擬宇宙祝福(遵循模擬宇宙任務設定)", "True": "已啟用" + }, + "AimClicker": { + "name": "點擊被瞄準破壞物和敵人", + "help": "", + "item_enemy": "點擊破壞物和敵人", + "item": "僅點擊破壞物", + "enemy": "僅點擊敵人", + "do_not_click": "不點擊" } }, "Gui": { diff --git a/module/device/platform/emulator_base.py b/module/device/platform/emulator_base.py index cdb475948..19262b083 100644 --- a/module/device/platform/emulator_base.py +++ b/module/device/platform/emulator_base.py @@ -83,8 +83,9 @@ class EmulatorInstanceBase: def MuMuPlayer12_id(self): """ Convert MuMu 12 instance name to instance id. - Example name: MuMuPlayer-12.0-3 - Example ID : 3 + Example names: + MuMuPlayer-12.0-3 + YXArkNights-12.0-1 Returns: int: Instance ID, or None if this is not a MuMu 12 instance @@ -92,8 +93,11 @@ class EmulatorInstanceBase: res = re.search(r'MuMuPlayer-12.0-(\d+)', self.name) if res: return int(res.group(1)) - else: - return None + res = re.search(r'YXArkNights-12.0-(\d+)', self.name) + if res: + return int(res.group(1)) + + return None class EmulatorBase: diff --git a/module/device/platform/emulator_windows.py b/module/device/platform/emulator_windows.py index a317ad4f5..379b7a7b3 100644 --- a/module/device/platform/emulator_windows.py +++ b/module/device/platform/emulator_windows.py @@ -330,8 +330,12 @@ class EmulatorManager(EmulatorManagerBase): path = r'Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist' # {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\xxx.exe regex_hash = re.compile(r'{.*}') - with winreg.OpenKey(winreg.HKEY_CURRENT_USER, path) as reg: - folders = list_key(reg) + try: + with winreg.OpenKey(winreg.HKEY_CURRENT_USER, path) as reg: + folders = list_key(reg) + except FileNotFoundError: + return + for folder in folders: try: with winreg.OpenKey(winreg.HKEY_CURRENT_USER, f'{path}\\{folder}\\Count') as reg: @@ -358,8 +362,11 @@ class EmulatorManager(EmulatorManagerBase): str: Path to emulator executable, may contains duplicate values """ path = r'Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache' - with winreg.OpenKey(winreg.HKEY_CURRENT_USER, path) as reg: - rows = list_reg(reg) + try: + with winreg.OpenKey(winreg.HKEY_CURRENT_USER, path) as reg: + rows = list_reg(reg) + except FileNotFoundError: + return regex = re.compile(r'(^.*\.exe)\.') for row in rows: @@ -425,24 +432,28 @@ class EmulatorManager(EmulatorManagerBase): 'MEmu', ] for path in known_uninstall_registry_path: - with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) as reg: - for software in list_key(reg): - if software not in known_emulator_registry_name: - continue + try: + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) as reg: + software_list = list_key(reg) + except FileNotFoundError: + continue + for software in software_list: + if software not in known_emulator_registry_name: + continue + try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f'{path}\\{software}') as software_reg: - try: - uninstall = winreg.QueryValueEx(software_reg, 'UninstallString')[0] - except FileNotFoundError: - continue - if not uninstall: - continue - # UninstallString is like: - # C:\Program Files\BlueStacks_nxt\BlueStacksUninstaller.exe -tmp - # "E:\ProgramFiles\Microvirt\MEmu\uninstall\uninstall.exe" -u - # Extract path in "" - res = re.search('"(.*?)"', uninstall) - uninstall = res.group(1) if res else uninstall - yield uninstall + uninstall = winreg.QueryValueEx(software_reg, 'UninstallString')[0] + except FileNotFoundError: + continue + if not uninstall: + continue + # UninstallString is like: + # C:\Program Files\BlueStacks_nxt\BlueStacksUninstaller.exe -tmp + # "E:\ProgramFiles\Microvirt\MEmu\uninstall\uninstall.exe" -u + # Extract path in "" + res = re.search('"(.*?)"', uninstall) + uninstall = res.group(1) if res else uninstall + yield uninstall @cached_property def all_emulators(self) -> t.List[Emulator]: diff --git a/module/device/platform/platform_windows.py b/module/device/platform/platform_windows.py index 049015663..36a58fb25 100644 --- a/module/device/platform/platform_windows.py +++ b/module/device/platform/platform_windows.py @@ -91,6 +91,8 @@ class PlatformWindows(PlatformBase, EmulatorManager): self.execute(f'"{exe}" -m {instance.name}') elif instance == Emulator.MuMuPlayer12: # MuMuPlayer.exe -v 0 + if instance.MuMuPlayer12_id is None: + logger.warning(f'Cannot get MuMu instance index from name {instance.name}') self.execute(f'"{exe}" -v {instance.MuMuPlayer12_id}') elif instance == Emulator.NoxPlayerFamily: # Nox.exe -clone:Nox_1 @@ -142,6 +144,8 @@ class PlatformWindows(PlatformBase, EmulatorManager): # MuMu 12 has 2 processes: # E:\ProgramFiles\Netease\MuMuPlayer-12.0\shell\MuMuPlayer.exe -v 0 # "C:\Program Files\MuMuVMMVbox\Hypervisor\MuMuVMMHeadless.exe" --comment MuMuPlayer-12.0-0 --startvm xxx + if instance.MuMuPlayer12_id is None: + logger.warning(f'Cannot get MuMu instance index from name {instance.name}') self.kill_process_by_regex( rf'(' rf'MuMuVMMHeadless.exe.*--comment {instance.name}' diff --git a/module/exception.py b/module/exception.py index e9bf713c6..2d027bb99 100644 --- a/module/exception.py +++ b/module/exception.py @@ -29,6 +29,13 @@ class GamePageUnknownError(Exception): pass +class TaskError(Exception): + # An error occurred in task, + # task itself should have error handled before raising TaskError, + # then task will be re-scheduled + pass + + class RequestHumanTakeover(Exception): # Request human takeover # Alas is unable to handle such error, probably because of wrong settings. diff --git a/module/ocr/keyword.py b/module/ocr/keyword.py index 4acfdc90e..3593b1d46 100644 --- a/module/ocr/keyword.py +++ b/module/ocr/keyword.py @@ -7,7 +7,7 @@ import module.config.server as server from module.exception import ScriptError # ord('.') = 65294 -REGEX_PUNCTUATION = re.compile(r'[ ,..\'"“”,。…::;;!!??·・•*※\-—-/\\\n\t()\[\]()「」『』【】《》[]]') +REGEX_PUNCTUATION = re.compile(r'[ ,..\'"“”,。…::;;!!??·・•●〇°*※\-—-/\\\n\t()\[\]()「」『』【】《》[]]') def parse_name(n): diff --git a/route/rogue/Combat/Luofu_Cloudford_F1.py b/route/rogue/Combat/Luofu_Cloudford_F1.py index 71f1dbae2..a89d53f6e 100644 --- a/route/rogue/Combat/Luofu_Cloudford_F1.py +++ b/route/rogue/Combat/Luofu_Cloudford_F1.py @@ -120,6 +120,8 @@ class Route(RouteBase): Luofu_Cloudford_F1_X281Y873 is the same as Luofu_Cloudford_F1_X283Y865 but for wrong spawn point detected """ + # Re-init position to be the same as origin + self.minimap.init_position(position=(283.4, 865.3), locked=True) self.clear_enemy(enemy) @locked_position diff --git a/tasks/assignment/assignment.py b/tasks/assignment/assignment.py index 2f21c93f2..758dd5af2 100644 --- a/tasks/assignment/assignment.py +++ b/tasks/assignment/assignment.py @@ -2,11 +2,9 @@ from datetime import datetime from module.logger import logger from tasks.assignment.claim import AssignmentClaim -from tasks.assignment.keywords import (KEYWORDS_ASSIGNMENT_GROUP, - AssignmentEntry, AssignmentEventGroup) +from tasks.assignment.keywords import (AssignmentEntry, AssignmentEventGroup, KEYWORDS_ASSIGNMENT_GROUP) from tasks.assignment.ui import AssignmentStatus from tasks.base.page import page_assignment, page_menu -from tasks.battle_pass.keywords import KEYWORD_BATTLE_PASS_QUEST from tasks.daily.keywords import KEYWORDS_DAILY_QUEST from tasks.daily.synthesize import SynthesizeUI diff --git a/tasks/assignment/keywords/__init__.py b/tasks/assignment/keywords/__init__.py index 9112ad297..ab95755a7 100644 --- a/tasks/assignment/keywords/__init__.py +++ b/tasks/assignment/keywords/__init__.py @@ -1,4 +1,5 @@ import tasks.assignment.keywords.entry as KEYWORDS_ASSIGNMENT_ENTRY +import tasks.assignment.keywords.entry_detailed as KEYWORDS_ASSIGNMENT_ENTRY_DETAILED import tasks.assignment.keywords.group as KEYWORDS_ASSIGNMENT_GROUP import tasks.assignment.keywords.event_entry as KEYWORDS_ASSIGNMENT_EVENT_ENTRY import tasks.assignment.keywords.event_group as KEYWORDS_ASSIGNMENT_EVENT_GROUP @@ -11,6 +12,8 @@ KEYWORDS_ASSIGNMENT_GROUP.Character_Materials.entries = ( KEYWORDS_ASSIGNMENT_ENTRY.Born_to_Obey, KEYWORDS_ASSIGNMENT_ENTRY.Root_Out_the_Turpitude, KEYWORDS_ASSIGNMENT_ENTRY.Fire_Lord_Inflames_Blades_of_War, + KEYWORDS_ASSIGNMENT_ENTRY.A_Startling_Night_Terror, + KEYWORDS_ASSIGNMENT_ENTRY.Tranquility_of_Vimala_bhumi, ) KEYWORDS_ASSIGNMENT_GROUP.EXP_Materials_Credits.entries = ( KEYWORDS_ASSIGNMENT_ENTRY.Nameless_Land_Nameless_People, @@ -24,6 +27,8 @@ KEYWORDS_ASSIGNMENT_GROUP.Synthesis_Materials.entries = ( KEYWORDS_ASSIGNMENT_ENTRY.The_Blossom_in_the_Storm, KEYWORDS_ASSIGNMENT_ENTRY.Legend_of_the_Puppet_Master, KEYWORDS_ASSIGNMENT_ENTRY.The_Wages_of_Humanity, + KEYWORDS_ASSIGNMENT_ENTRY.Fragments_of_Illusory_Dreams, + KEYWORDS_ASSIGNMENT_ENTRY.Scalpel_and_Screwdriver, ) KEYWORDS_ASSIGNMENT_EVENT_GROUP.Space_Station_Task_Force.entries = ( KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Repulsion_Bridge_Errors, diff --git a/tasks/assignment/keywords/classes.py b/tasks/assignment/keywords/classes.py index e5a7c774d..cbb2cd008 100644 --- a/tasks/assignment/keywords/classes.py +++ b/tasks/assignment/keywords/classes.py @@ -20,6 +20,11 @@ class AssignmentEntry(Keyword): return super().__hash__() +@dataclass(repr=False) +class AssignmentEntryDetailed(Keyword): + instances: ClassVar = {} + + @dataclass(repr=False) class AssignmentEventGroup(AssignmentGroup): instances: ClassVar = {} diff --git a/tasks/assignment/keywords/entry.py b/tasks/assignment/keywords/entry.py index 65325ad22..cab71c000 100644 --- a/tasks/assignment/keywords/entry.py +++ b/tasks/assignment/keywords/entry.py @@ -57,8 +57,26 @@ Fire_Lord_Inflames_Blades_of_War = AssignmentEntry( jp='剣戟を焼却する火帝炉', es='Prendan los fuelles, fundan las armas', ) -Nameless_Land_Nameless_People = AssignmentEntry( +A_Startling_Night_Terror = AssignmentEntry( id=7, + name='A_Startling_Night_Terror', + cn='劫梦惊魂', + cht='劫夢驚魂', + en='A Startling Night Terror', + jp='魂震える悪夢', + es='Pesadilla aterradora', +) +Tranquility_of_Vimala_bhumi = AssignmentEntry( + id=8, + name='Tranquility_of_Vimala_bhumi', + cn='离垢清净', + cht='離垢清淨', + en='Tranquility of Vimala-bhumi', + jp='離垢清浄', + es='Limpieza y purificación', +) +Nameless_Land_Nameless_People = AssignmentEntry( + id=9, name='Nameless_Land_Nameless_People', cn='无名之地,无名之人', cht='無名之地,無名之人', @@ -67,7 +85,7 @@ Nameless_Land_Nameless_People = AssignmentEntry( es='Lugar anónimo, personas anónimas', ) Akashic_Records = AssignmentEntry( - id=8, + id=10, name='Akashic_Records', cn='阿卡夏记录', cht='阿卡夏紀錄', @@ -76,7 +94,7 @@ Akashic_Records = AssignmentEntry( es='Los Registros de Akasha', ) The_Invisible_Hand = AssignmentEntry( - id=9, + id=11, name='The_Invisible_Hand', cn='看不见的手', cht='看不見的手', @@ -85,7 +103,7 @@ The_Invisible_Hand = AssignmentEntry( es='La mano invisible', ) Abandoned_and_Insulted = AssignmentEntry( - id=10, + id=12, name='Abandoned_and_Insulted', cn='被废弃与损害的', cht='被廢棄與損害的', @@ -94,7 +112,7 @@ Abandoned_and_Insulted = AssignmentEntry( es='Abandonado e insultado', ) Spring_of_Life = AssignmentEntry( - id=11, + id=13, name='Spring_of_Life', cn='生命之泉', cht='生命之泉', @@ -103,7 +121,7 @@ Spring_of_Life = AssignmentEntry( es='La fuente de la vida', ) The_Land_of_Gold = AssignmentEntry( - id=12, + id=14, name='The_Land_of_Gold', cn='黄金大地', cht='黃金大地', @@ -112,7 +130,7 @@ The_Land_of_Gold = AssignmentEntry( es='Tierra de oportunidades', ) The_Blossom_in_the_Storm = AssignmentEntry( - id=13, + id=15, name='The_Blossom_in_the_Storm', cn='风暴中怒放的花', cht='風暴中怒放的花', @@ -121,7 +139,7 @@ The_Blossom_in_the_Storm = AssignmentEntry( es='Flores en la tormenta', ) Legend_of_the_Puppet_Master = AssignmentEntry( - id=14, + id=16, name='Legend_of_the_Puppet_Master', cn='偃师传说', cht='偃師傳說', @@ -130,7 +148,7 @@ Legend_of_the_Puppet_Master = AssignmentEntry( es='La leyenda del titiritero', ) The_Wages_of_Humanity = AssignmentEntry( - id=15, + id=17, name='The_Wages_of_Humanity', cn='赡养人类', cht='贍養人類', @@ -138,3 +156,21 @@ The_Wages_of_Humanity = AssignmentEntry( jp='人類扶養', es='La paga de la humanidad', ) +Fragments_of_Illusory_Dreams = AssignmentEntry( + id=18, + name='Fragments_of_Illusory_Dreams', + cn='幻梦的残片', + cht='幻夢的殘片', + en='Fragments of Illusory Dreams', + jp='幻夢の残片', + es='Fragmentos de sueños ilusorios', +) +Scalpel_and_Screwdriver = AssignmentEntry( + id=19, + name='Scalpel_and_Screwdriver', + cn='手术刀与螺丝刀', + cht='手術刀與螺絲起子', + en='Scalpel and Screwdriver', + jp='メスとスクリュードライバー', + es='Bisturí y destornillador', +) diff --git a/tasks/assignment/keywords/entry_detailed.py b/tasks/assignment/keywords/entry_detailed.py new file mode 100644 index 000000000..418e8f578 --- /dev/null +++ b/tasks/assignment/keywords/entry_detailed.py @@ -0,0 +1,176 @@ +from .classes import AssignmentEntryDetailed + +# This file was auto-generated, do not modify it manually. To generate: +# ``` python -m dev_tools.keyword_extract ``` + +Nine_Billion_Names = AssignmentEntryDetailed( + id=1, + name='Nine_Billion_Names', + cn='熄灭原核(九十亿个名字)', + cht='熄滅原核(九十億個名字)', + en='Extinguished Core (Nine Billion Names)', + jp='消滅した原核(九十億の御名)', + es='Núcleo apagado (Nueve mil millones de nombres)', +) +Destruction_of_the_Destroyer = AssignmentEntryDetailed( + id=2, + name='Destruction_of_the_Destroyer', + cn='掠夺的本能(毁灭者的覆灭)', + cht='掠奪的本能(毀滅者的覆滅)', + en="Thief's Instinct (Destruction of the Destroyer)", + jp='略奪の本能(壊滅者の覆没)', + es='Instinto del ladrón (La destrucción del destructor)', +) +Winter_Soldiers = AssignmentEntryDetailed( + id=3, + name='Winter_Soldiers', + cn='铁卫扣饰(寒冬的战士们)', + cht='鐵衛扣飾(寒冬的戰士們)', + en='Silvermane Badge (Winter Soldiers)', + jp='シルバーメインの釦(寒冬の戦士たち)', + es='Pin del guardia (Los guerreros del invierno)', +) +Born_to_Obey = AssignmentEntryDetailed( + id=4, + name='Born_to_Obey', + cn='古代零件(生而服从)', + cht='古代零件(生而服從)', + en='Ancient Part (Born to Obey)', + jp='古代パーツ(生まれながらに服従する)', + es='Componente antiguo (Creados para obedecer)', +) +Root_Out_the_Turpitude = AssignmentEntryDetailed( + id=5, + name='Root_Out_the_Turpitude', + cn='永寿幼芽(根除恶孽)', + cht='永壽幼芽(根除惡孽)', + en='Immortal Scionette (Root Out the Turpitude)', + jp='永寿の萌芽(悪孽を根絶やしに)', + es='Brote verde inmortal (La raíz del mal)', +) +Fire_Lord_Inflames_Blades_of_War = AssignmentEntryDetailed( + id=6, + name='Fire_Lord_Inflames_Blades_of_War', + cn='工造机杼(火帝动炉销剑戟)', + cht='工造機杼(火帝動爐銷劍戟)', + en="Artifex's Module (Fire Lord Inflames Blades of War)", + jp='工造機関(剣戟を焼却する火帝炉)', + es='Componente artificial mecánico (Prendan los fuelles, fundan las armas)', +) +A_Startling_Night_Terror = AssignmentEntryDetailed( + id=7, + name='A_Startling_Night_Terror', + cn='蓄梦元件(劫梦惊魂)', + cht='蓄夢元件(劫夢驚魂)', + en='Dream Collection Component (A Startling Night Terror)', + jp='ドリームコレクションパーツ(魂震える悪夢)', + es='Componente del acumulador de sueños (Pesadilla aterradora)', +) +Tranquility_of_Vimala_bhumi = AssignmentEntryDetailed( + id=8, + name='Tranquility_of_Vimala_bhumi', + cn='思绪末屑(离垢清净)', + cht='思緒末屑(離垢清淨)', + en='Tatters of Thought (Tranquility of Vimala-bhumi)', + jp='思考の粉末(離垢清浄)', + es='Jirones de pensamientos (Limpieza y purificación)', +) +Nameless_Land_Nameless_People = AssignmentEntryDetailed( + id=9, + name='Nameless_Land_Nameless_People', + cn='角色经验材料(无名之地,无名之人)', + cht='角色經驗素材(無名之地,無名之人)', + en='Character EXP Material (Nameless Land, Nameless People)', + jp='キャラクター経験値素材(無名の地、無名の人)', + es='Material de EXP de personaje (Lugar anónimo, personas anónimas)', +) +Akashic_Records = AssignmentEntryDetailed( + id=10, + name='Akashic_Records', + cn='光锥经验材料(阿卡夏记录)', + cht='光錐經驗素材(阿卡夏紀錄)', + en='Light Cone EXP Material (Akashic Records)', + jp='光円錐経験値素材(アーカーシャの記録)', + es='Material de EXP de conos de luz (Los Registros de Akasha)', +) +The_Invisible_Hand = AssignmentEntryDetailed( + id=11, + name='The_Invisible_Hand', + cn='信用点(看不见的手)', + cht='信用點(看不見的手)', + en='Credit (The Invisible Hand)', + jp='信用ポイント(見えざる手)', + es='Crédito (La mano invisible)', +) +Abandoned_and_Insulted = AssignmentEntryDetailed( + id=12, + name='Abandoned_and_Insulted', + cn='燃素 & 金属(被废弃与损害的)', + cht='燃素 & 金屬(被廢棄與損害的)', + en='Phlogiston & Metal (Abandoned and Insulted)', + jp='燃素 & 金属(捨てられしものと傷つけられしもの)', + es='Flogisto & Metal (Abandonado e insultado)', +) +Spring_of_Life = AssignmentEntryDetailed( + id=13, + name='Spring_of_Life', + cn='固态净水 & 虚粒子(生命之泉)', + cht='固態淨水 & 虛粒子(生命之泉)', + en='Solid Water & Virtual Particle (Spring of Life)', + jp='固形純水 & 仮想粒子(生命の泉)', + es='Agua sólida & Partícula virtual (La fuente de la vida)', +) +The_Land_of_Gold = AssignmentEntryDetailed( + id=14, + name='The_Land_of_Gold', + cn='基本食材 & 蛋白米(黄金大地)', + cht='基本食材 & 蛋白米(黃金大地)', + en='Basic Ingredients & Protein Rice (The Land of Gold)', + jp='基本食材 & タンパク米(黄金の大地)', + es='Ingredientes básicos & Arroz proteico (Tierra de oportunidades)', +) +The_Blossom_in_the_Storm = AssignmentEntryDetailed( + id=15, + name='The_Blossom_in_the_Storm', + cn='气态流体 & 种子(风暴中怒放的花)', + cht='氣態流體 & 種子(風暴中怒放的花)', + en='Gaseous Liquid & Seed (The Blossom in the Storm)', + jp='気態流体 & 種子(嵐の中で咲き誇る花)', + es='Líquido gaseoso & Semilla (Flores en la tormenta)', +) +Legend_of_the_Puppet_Master = AssignmentEntryDetailed( + id=16, + name='Legend_of_the_Puppet_Master', + cn='废弃机巧零件 & 玉兆单元(偃师传说)', + cht='廢棄機巧零件 & 玉兆單元(偃師傳說)', + en='Discarded Ingenium Parts & Jade Abacus Unit (Legend of the Puppet Master)', + jp='廃棄された機巧部品 & 玉兆単元(傀儡師伝説)', + es='Componentes mecánicos abandonados & Unidad de ábaco de jade (La leyenda del titiritero)', +) +The_Wages_of_Humanity = AssignmentEntryDetailed( + id=17, + name='The_Wages_of_Humanity', + cn='一人嘉禾 & 药草提取物(赡养人类)', + cht='一人嘉禾 & 藥草萃取物(贍養人類)', + en='Human-Height Auspicious Crops & Extract of Medicinal Herbs (The Wages of Humanity)', + jp='一人稲 & 薬草抽出物(人類扶養)', + es='Cosecha tan alta como una persona & Extracto de hierbas medicinales (La paga de la humanidad)', +) +Fragments_of_Illusory_Dreams = AssignmentEntryDetailed( + id=18, + name='Fragments_of_Illusory_Dreams', + cn='安逸 & 碎梦(幻梦的残片)', + cht='安逸 & 碎夢(幻夢的殘片)', + en='Tranquility & Broken Dreams (Fragments of Illusory Dreams)', + jp='安逸 & 砕けた夢(幻夢の残片)', + es='Tranquilidad & Sueños rotos (Fragmentos de sueños ilusorios)', +) +Scalpel_and_Screwdriver = AssignmentEntryDetailed( + id=19, + name='Scalpel_and_Screwdriver', + cn='锈迹齿轮 & 老旧臼齿(手术刀与螺丝刀)', + cht='鏽跡齒輪 & 老舊臼齒(手術刀與螺絲起子)', + en='Rusty Gear & Old Molar (Scalpel and Screwdriver)', + jp='錆びた歯車 & 古びた大臼歯(メスとスクリュードライバー)', + es='Engranaje oxidado & Muela vieja (Bisturí y destornillador)', +) diff --git a/tasks/base/assets/assets_base_page.py b/tasks/base/assets/assets_base_page.py index 90684c6e7..7480b5ddf 100644 --- a/tasks/base/assets/assets_base_page.py +++ b/tasks/base/assets/assets_base_page.py @@ -144,13 +144,22 @@ MAIN_GOTO_BATTLE_PASS = ButtonWrapper( ) MAIN_GOTO_CHARACTER = ButtonWrapper( name='MAIN_GOTO_CHARACTER', - share=Button( - file='./assets/share/base/page/MAIN_GOTO_CHARACTER.png', - area=(1204, 25, 1234, 51), - search=(1184, 5, 1254, 71), - color=(184, 185, 187), - button=(1204, 25, 1234, 51), - ), + share=[ + Button( + file='./assets/share/base/page/MAIN_GOTO_CHARACTER.png', + area=(1204, 25, 1234, 51), + search=(1184, 5, 1254, 71), + color=(184, 185, 187), + button=(1204, 25, 1234, 51), + ), + Button( + file='./assets/share/base/page/MAIN_GOTO_CHARACTER.2.png', + area=(1204, 25, 1234, 51), + search=(1184, 5, 1254, 71), + color=(211, 181, 211), + button=(1204, 25, 1234, 51), + ), + ], ) MAIN_GOTO_EVENT = ButtonWrapper( name='MAIN_GOTO_EVENT', diff --git a/tasks/base/daemon.py b/tasks/base/daemon.py index 572a3ebd5..537d6e5b5 100644 --- a/tasks/base/daemon.py +++ b/tasks/base/daemon.py @@ -1,18 +1,68 @@ from module.base.timer import Timer +from module.daemon.daemon_base import DaemonBase +from module.device.method import maatouch from module.logger import logger from tasks.base.assets.assets_base_daemon import * from tasks.base.main_page import MainPage from tasks.base.page import page_main, page_rogue from tasks.daily.assets.assets_daily_camera import PICTURE_TAKEN from tasks.map.assets.assets_map_bigmap import TELEPORT_RIGHT +from tasks.map.interact.aim import AimDetectorMixin from tasks.rogue.route.base import RouteBase -class Daemon(RouteBase): +class SecondaryMaatouchBuilder(maatouch.MaatouchBuilder): + def __init__(self, device, contact=0, handle_orientation=False): + """ + Click on secondary contact to avoid interruption of real-person contact + """ + super().__init__(device, contact=1, handle_orientation=handle_orientation) + + +maatouch.MaatouchBuilder = SecondaryMaatouchBuilder + + +class Daemon(RouteBase, DaemonBase, AimDetectorMixin): + aim_interval = Timer(0.3, count=1) + + def handle_aim_click(self, item=True, enemy=True): + """ + Args: + item: + enemy: + + Returns: + bool: If clicked + """ + if not item and not enemy: + return False + if not self.is_in_main(): + return False + + if self.aim_interval.reached_and_reset(): + self.aim.predict(self.device.image, item=item, enemy=enemy) + if self.aim.aimed_enemy: + if self.handle_map_A(): + return True + if self.aim.aimed_item: + if self.handle_map_A(): + return True + return False + def run(self): # Rebind daemon settings along with rogue settings self.config.bind('Daemon', func_list=['Rogue']) - self.device.disable_stuck_detection() + # Check contact + builder = self.device.maatouch_builder + if builder.contact >= 1: + logger.info(f'Maatouch contact on {builder.contact}') + else: + logger.warning(f'Maatouch contact on {builder.contact}, may cause interruptions') + + STORY_OPTION.set_search_offset((-5, -5, 32, 5)) + INTERACT_COLLECT.set_search_offset((-5, -5, 32, 5)) + INTERACT_INVESTIGATE.set_search_offset((-5, -5, 32, 5)) + INTERACT_TREASURE.set_search_offset((-5, -5, 32, 5)) teleport_confirm = Timer(1, count=5) while 1: @@ -65,3 +115,9 @@ class Daemon(RouteBase): continue if self.handle_event_option(): continue + # Aim click + if self.handle_aim_click( + item='item' in self.config.Daemon_AimClicker, + enemy='enemy' in self.config.Daemon_AimClicker, + ): + continue diff --git a/tasks/battle_pass/battle_pass.py b/tasks/battle_pass/battle_pass.py index b1c684c37..a7e172b41 100644 --- a/tasks/battle_pass/battle_pass.py +++ b/tasks/battle_pass/battle_pass.py @@ -20,14 +20,22 @@ from tasks.base.ui import UI from tasks.battle_pass.assets.assets_battle_pass import * from tasks.battle_pass.keywords import * -SWITCH_BATTLE_PASS_TAB = Switch('BattlePassTab', is_selector=True) + +class BattlePassTab(Switch): + def handle_additional(self, main: UI): + if main.handle_reward(): + return True + return False + + +SWITCH_BATTLE_PASS_TAB = BattlePassTab('BattlePassTab', is_selector=True) SWITCH_BATTLE_PASS_TAB.add_state( - KEYWORD_BATTLE_PASS_TAB.Rewards, + KEYWORDS_BATTLE_PASS_TAB.Rewards, check_button=REWARDS_CHECK, click_button=REWARDS_CLICK ) SWITCH_BATTLE_PASS_TAB.add_state( - KEYWORD_BATTLE_PASS_TAB.Missions, + KEYWORDS_BATTLE_PASS_TAB.Missions, check_button=MISSIONS_CHECK, click_button=MISSIONS_CLICK ) @@ -51,12 +59,12 @@ class BattlePassMissionTab(Switch): SWITCH_BATTLE_PASS_MISSION_TAB = BattlePassMissionTab('BattlePassMissionTab', is_selector=True) SWITCH_BATTLE_PASS_MISSION_TAB.add_state( - KEYWORD_BATTLE_PASS_MISSION_TAB.This_Week_Missions, + KEYWORDS_BATTLE_PASS_MISSION_TAB.This_Week_Missions, check_button=WEEK_MISSION_CLICK, click_button=WEEK_MISSION_CLICK ) SWITCH_BATTLE_PASS_MISSION_TAB.add_state( - KEYWORD_BATTLE_PASS_MISSION_TAB.This_Period_Missions, + KEYWORDS_BATTLE_PASS_MISSION_TAB.This_Period_Missions, check_button=PERIOD_MISSION_CLICK, click_button=PERIOD_MISSION_CLICK ) @@ -81,7 +89,7 @@ class DataBattlePassQuest: @property def is_incomplete(self) -> bool: - return self.state == KEYWORD_BATTLE_PASS_QUEST_STATE.Navigate + return self.state == KEYWORDS_BATTLE_PASS_QUEST_STATE.Navigate class BattlePassUI(UI): @@ -121,7 +129,7 @@ class BattlePassUI(UI): logger.info('Missions tab loaded') break - def battle_pass_goto(self, state: KEYWORD_BATTLE_PASS_TAB): + def battle_pass_goto(self, state: KEYWORDS_BATTLE_PASS_TAB): """ Args: state: @@ -135,18 +143,18 @@ class BattlePassUI(UI): self.ui_ensure(page_battle_pass) if SWITCH_BATTLE_PASS_TAB.set(state, main=self): logger.info(f'Tab goto {state}, wait until loaded') - if state == KEYWORD_BATTLE_PASS_TAB.Missions: + if state == KEYWORDS_BATTLE_PASS_TAB.Missions: self._battle_pass_wait_missions_loaded() - if state == KEYWORD_BATTLE_PASS_TAB.Rewards: + if state == KEYWORDS_BATTLE_PASS_TAB.Rewards: self._battle_pass_wait_rewards_loaded() - def battle_pass_mission_tab_goto(self, state: KEYWORD_BATTLE_PASS_MISSION_TAB): - self.battle_pass_goto(KEYWORD_BATTLE_PASS_TAB.Missions) + def battle_pass_mission_tab_goto(self, state: KEYWORDS_BATTLE_PASS_MISSION_TAB): + self.battle_pass_goto(KEYWORDS_BATTLE_PASS_TAB.Missions) if SWITCH_BATTLE_PASS_MISSION_TAB.set(state, main=self): logger.info(f'Tab goto {state}, wait until loaded') - if state == KEYWORD_BATTLE_PASS_MISSION_TAB.This_Week_Missions: + if state == KEYWORDS_BATTLE_PASS_MISSION_TAB.This_Week_Missions: self._battle_pass_wait_missions_loaded() - if state == KEYWORD_BATTLE_PASS_MISSION_TAB.This_Period_Missions: + if state == KEYWORDS_BATTLE_PASS_MISSION_TAB.This_Period_Missions: self._battle_pass_wait_missions_loaded() def handle_choose_gifts(self, interval=5): @@ -166,7 +174,7 @@ class BattlePassUI(UI): def _claim_exp(self, skip_first_screenshot=True): logger.hr('Claim EXP', level=1) - self.battle_pass_goto(KEYWORD_BATTLE_PASS_TAB.Missions) + self.battle_pass_goto(KEYWORDS_BATTLE_PASS_TAB.Missions) claimed = False while 1: if skip_first_screenshot: @@ -187,7 +195,7 @@ class BattlePassUI(UI): def _claim_rewards(self, skip_first_screenshot=True): logger.hr('Claim rewards', level=1) - self.battle_pass_goto(KEYWORD_BATTLE_PASS_TAB.Rewards) + self.battle_pass_goto(KEYWORDS_BATTLE_PASS_TAB.Rewards) timeout = Timer(5, count=15).start() while 1: if skip_first_screenshot: @@ -297,11 +305,11 @@ class BattlePassUI(UI): def battle_pass_quests_recognition(self): """ Pages: - in: page_battle_pass, KEYWORD_BATTLE_PASS_TAB.Missions, weekly or period + in: page_battle_pass, KEYWORDS_BATTLE_PASS_TAB.Missions, weekly or period """ logger.hr('Quest recognise', level=1) self.battle_pass_mission_tab_goto( - KEYWORD_BATTLE_PASS_MISSION_TAB.This_Week_Missions) + KEYWORDS_BATTLE_PASS_MISSION_TAB.This_Week_Missions) scroll = Scroll(MISSION_PAGE_SCROLL, color=(198, 198, 198)) scroll.set_top(main=self) @@ -319,19 +327,19 @@ class BattlePassUI(UI): # Convert quest keyword to stored object dic_quest_to_stored = { - KEYWORD_BATTLE_PASS_QUEST.Complete_Simulated_Universe_1_times: + KEYWORDS_BATTLE_PASS_QUEST.Complete_Simulated_Universe_1_times: self.config.stored.BattlePassSimulatedUniverse, - KEYWORD_BATTLE_PASS_QUEST.Clear_Calyx_1_times: + KEYWORDS_BATTLE_PASS_QUEST.Clear_Calyx_1_times: self.config.stored.BattlePassQuestCalyx, - KEYWORD_BATTLE_PASS_QUEST.Complete_Echo_of_War_1_times: + KEYWORDS_BATTLE_PASS_QUEST.Complete_Echo_of_War_1_times: self.config.stored.BattlePassQuestEchoOfWar, - KEYWORD_BATTLE_PASS_QUEST.Use_300000_credits: + KEYWORDS_BATTLE_PASS_QUEST.Use_300000_credits: self.config.stored.BattlePassQuestCredits, - KEYWORD_BATTLE_PASS_QUEST.Synthesize_Consumables_1_times: + KEYWORDS_BATTLE_PASS_QUEST.Synthesize_Consumables_1_times: self.config.stored.BattlePassQuestSynthesizeConsumables, - KEYWORD_BATTLE_PASS_QUEST.Clear_Cavern_of_Corrosion_1_times: + KEYWORDS_BATTLE_PASS_QUEST.Clear_Cavern_of_Corrosion_1_times: self.config.stored.BattlePassQuestCavernOfCorrosion, - KEYWORD_BATTLE_PASS_QUEST.Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max: + KEYWORDS_BATTLE_PASS_QUEST.Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max: self.config.stored.BattlePassQuestTrailblazePower, } with self.config.multi_set(): diff --git a/tasks/battle_pass/keywords/__init__.py b/tasks/battle_pass/keywords/__init__.py index 2cfa8f449..6e5e5a7b8 100644 --- a/tasks/battle_pass/keywords/__init__.py +++ b/tasks/battle_pass/keywords/__init__.py @@ -1,6 +1,6 @@ -import tasks.battle_pass.keywords.mission_tab as KEYWORD_BATTLE_PASS_MISSION_TAB -import tasks.battle_pass.keywords.quest as KEYWORD_BATTLE_PASS_QUEST -import tasks.battle_pass.keywords.quest_state as KEYWORD_BATTLE_PASS_QUEST_STATE -import tasks.battle_pass.keywords.tab as KEYWORD_BATTLE_PASS_TAB +import tasks.battle_pass.keywords.mission_tab as KEYWORDS_BATTLE_PASS_MISSION_TAB +import tasks.battle_pass.keywords.quest as KEYWORDS_BATTLE_PASS_QUEST +import tasks.battle_pass.keywords.quest_state as KEYWORDS_BATTLE_PASS_QUEST_STATE +import tasks.battle_pass.keywords.tab as KEYWORDS_BATTLE_PASS_TAB from tasks.battle_pass.keywords.classes import BattlePassTab, BattlePassMissionTab, BattlePassQuest, \ BattlePassQuestState diff --git a/tasks/character/assets/assets_character_switch.py b/tasks/character/assets/assets_character_switch.py index 0ac313f84..aa17d8c66 100644 --- a/tasks/character/assets/assets_character_switch.py +++ b/tasks/character/assets/assets_character_switch.py @@ -3,6 +3,16 @@ 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 ``` +Huohuo = ButtonWrapper( + name='Huohuo', + share=Button( + file='./assets/share/character/switch/Huohuo.png', + area=(1171, 162, 1189, 180), + search=(1151, 142, 1209, 200), + color=(187, 181, 173), + button=(1171, 162, 1189, 180), + ), +) OCR_MAP_CHARACTERS = ButtonWrapper( name='OCR_MAP_CHARACTERS', share=Button( diff --git a/tasks/character/keywords/__init__.py b/tasks/character/keywords/__init__.py index 3e2442cc4..cde9badfe 100644 --- a/tasks/character/keywords/__init__.py +++ b/tasks/character/keywords/__init__.py @@ -1,13 +1,17 @@ -import tasks.character.keywords.character_list as KEYWORD_CHARACTER_LIST +import tasks.character.keywords.character_list as KEYWORDS_CHARACTER_LIST +import tasks.character.keywords.combat_type as KEYWORDS_COMBAT_TYPE from tasks.character.keywords.character_list import * -from tasks.character.keywords.classes import CharacterList +from tasks.character.keywords.classes import CharacterList, CombatType DICT_SORTED_RANGES = { # Mage, hit instantly, no trajectories 'Mage': [ + RuanMei, DanHengImbibitorLunae, Welt, FuXuan, + # Longer precast + BlackSwan, ], # Mage, but character moved after attack 'MageSecondary': [ diff --git a/tasks/character/keywords/character_list.py b/tasks/character/keywords/character_list.py index 4c58396b5..3470b79e4 100644 --- a/tasks/character/keywords/character_list.py +++ b/tasks/character/keywords/character_list.py @@ -39,8 +39,17 @@ Bailu = CharacterList( jp='白露', es='Bailu', ) -Blade = CharacterList( +BlackSwan = CharacterList( id=5, + name='BlackSwan', + cn='黑天鹅', + cht='黑天鵝', + en='Black Swan', + jp='ブラックスワン', + es='Cisne Negro', +) +Blade = CharacterList( + id=6, name='Blade', cn='刃', cht='刃', @@ -49,7 +58,7 @@ Blade = CharacterList( es='Blade', ) Bronya = CharacterList( - id=6, + id=7, name='Bronya', cn='布洛妮娅', cht='布洛妮婭', @@ -58,7 +67,7 @@ Bronya = CharacterList( es='Bronya', ) Clara = CharacterList( - id=7, + id=8, name='Clara', cn='克拉拉', cht='克拉拉', @@ -67,7 +76,7 @@ Clara = CharacterList( es='Clara', ) DanHeng = CharacterList( - id=8, + id=9, name='DanHeng', cn='丹恒', cht='丹恆', @@ -76,7 +85,7 @@ DanHeng = CharacterList( es='Dan Heng', ) DanHengImbibitorLunae = CharacterList( - id=9, + id=10, name='DanHengImbibitorLunae', cn='丹恒•饮月', cht='丹恆•飲月', @@ -85,7 +94,7 @@ DanHengImbibitorLunae = CharacterList( es='Dan Heng - Imbibitor Lunae', ) DrRatio = CharacterList( - id=10, + id=11, name='DrRatio', cn='真理医生', cht='真理醫生', @@ -94,7 +103,7 @@ DrRatio = CharacterList( es='Dr. Ratio', ) FuXuan = CharacterList( - id=11, + id=12, name='FuXuan', cn='符玄', cht='符玄', @@ -103,7 +112,7 @@ FuXuan = CharacterList( es='Fu Xuan', ) Gepard = CharacterList( - id=12, + id=13, name='Gepard', cn='杰帕德', cht='傑帕德', @@ -112,7 +121,7 @@ Gepard = CharacterList( es='Gepard', ) Guinaifen = CharacterList( - id=13, + id=14, name='Guinaifen', cn='桂乃芬', cht='桂乃芬', @@ -121,7 +130,7 @@ Guinaifen = CharacterList( es='Guinaifen', ) Hanya = CharacterList( - id=14, + id=15, name='Hanya', cn='寒鸦', cht='寒鴉', @@ -130,7 +139,7 @@ Hanya = CharacterList( es='Hanya', ) Herta = CharacterList( - id=15, + id=16, name='Herta', cn='黑塔', cht='黑塔', @@ -139,7 +148,7 @@ Herta = CharacterList( es='Herta', ) Himeko = CharacterList( - id=16, + id=17, name='Himeko', cn='姬子', cht='姬子', @@ -148,7 +157,7 @@ Himeko = CharacterList( es='Himeko', ) Hook = CharacterList( - id=17, + id=18, name='Hook', cn='虎克', cht='虎克', @@ -157,7 +166,7 @@ Hook = CharacterList( es='Hook', ) Huohuo = CharacterList( - id=18, + id=19, name='Huohuo', cn='藿藿', cht='藿藿', @@ -166,7 +175,7 @@ Huohuo = CharacterList( es='Huohuo', ) JingYuan = CharacterList( - id=19, + id=20, name='JingYuan', cn='景元', cht='景元', @@ -175,7 +184,7 @@ JingYuan = CharacterList( es='Jing Yuan', ) Jingliu = CharacterList( - id=20, + id=21, name='Jingliu', cn='镜流', cht='鏡流', @@ -184,7 +193,7 @@ Jingliu = CharacterList( es='Jingliu', ) Kafka = CharacterList( - id=21, + id=22, name='Kafka', cn='卡芙卡', cht='卡芙卡', @@ -193,7 +202,7 @@ Kafka = CharacterList( es='Kafka', ) Luka = CharacterList( - id=22, + id=23, name='Luka', cn='卢卡', cht='盧卡', @@ -202,7 +211,7 @@ Luka = CharacterList( es='Luka', ) Luocha = CharacterList( - id=23, + id=24, name='Luocha', cn='罗刹', cht='羅剎', @@ -211,7 +220,7 @@ Luocha = CharacterList( es='Luocha', ) Lynx = CharacterList( - id=24, + id=25, name='Lynx', cn='玲可', cht='玲可', @@ -220,7 +229,7 @@ Lynx = CharacterList( es='Lynx', ) March7th = CharacterList( - id=25, + id=26, name='March7th', cn='三月七', cht='三月七', @@ -228,8 +237,17 @@ March7th = CharacterList( jp='三月なのか', es='Siete de Marzo', ) +Misha = CharacterList( + id=27, + name='Misha', + cn='米沙', + cht='米沙', + en='Misha', + jp='ミーシャ', + es='Misha', +) Natasha = CharacterList( - id=26, + id=28, name='Natasha', cn='娜塔莎', cht='娜塔莎', @@ -238,7 +256,7 @@ Natasha = CharacterList( es='Natasha', ) Pela = CharacterList( - id=27, + id=29, name='Pela', cn='佩拉', cht='佩拉', @@ -247,7 +265,7 @@ Pela = CharacterList( es='Pela', ) Qingque = CharacterList( - id=28, + id=30, name='Qingque', cn='青雀', cht='青雀', @@ -256,7 +274,7 @@ Qingque = CharacterList( es='Qingque', ) RuanMei = CharacterList( - id=29, + id=31, name='RuanMei', cn='阮•梅', cht='阮•梅', @@ -265,7 +283,7 @@ RuanMei = CharacterList( es='Ruan Mei', ) Sampo = CharacterList( - id=30, + id=32, name='Sampo', cn='桑博', cht='桑博', @@ -274,7 +292,7 @@ Sampo = CharacterList( es='Sampo', ) Seele = CharacterList( - id=31, + id=33, name='Seele', cn='希儿', cht='希兒', @@ -283,7 +301,7 @@ Seele = CharacterList( es='Seele', ) Serval = CharacterList( - id=32, + id=34, name='Serval', cn='希露瓦', cht='希露瓦', @@ -292,7 +310,7 @@ Serval = CharacterList( es='Serval', ) SilverWolf = CharacterList( - id=33, + id=35, name='SilverWolf', cn='银狼', cht='銀狼', @@ -300,8 +318,17 @@ SilverWolf = CharacterList( jp='銀狼', es='Silver Wolf', ) +Sparkle = CharacterList( + id=36, + name='Sparkle', + cn='花火', + cht='花火', + en='Sparkle', + jp='花火', + es='Sparkle', +) Sushang = CharacterList( - id=34, + id=37, name='Sushang', cn='素裳', cht='素裳', @@ -310,7 +337,7 @@ Sushang = CharacterList( es='Sushang', ) Tingyun = CharacterList( - id=35, + id=38, name='Tingyun', cn='停云', cht='停雲', @@ -319,7 +346,7 @@ Tingyun = CharacterList( es='Tingyun', ) TopazNumby = CharacterList( - id=36, + id=39, name='TopazNumby', cn='托帕&账账', cht='托帕&帳帳', @@ -328,7 +355,7 @@ TopazNumby = CharacterList( es='Topaz y Conti', ) TrailblazerDestruction = CharacterList( - id=37, + id=40, name='TrailblazerDestruction', cn='Trailblazer•毁灭', cht='Trailblazer•毀滅', @@ -337,7 +364,7 @@ TrailblazerDestruction = CharacterList( es='Trailblazer: Destrucción', ) TrailblazerPreservation = CharacterList( - id=38, + id=41, name='TrailblazerPreservation', cn='Trailblazer•存护', cht='Trailblazer•存護', @@ -346,7 +373,7 @@ TrailblazerPreservation = CharacterList( es='Trailblazer: Conservación', ) Welt = CharacterList( - id=39, + id=42, name='Welt', cn='瓦尔特', cht='瓦爾特', @@ -355,7 +382,7 @@ Welt = CharacterList( es='Welt', ) Xueyi = CharacterList( - id=40, + id=43, name='Xueyi', cn='雪衣', cht='雪衣', @@ -364,7 +391,7 @@ Xueyi = CharacterList( es='Xueyi', ) Yanqing = CharacterList( - id=41, + id=44, name='Yanqing', cn='彦卿', cht='彥卿', @@ -373,7 +400,7 @@ Yanqing = CharacterList( es='Yanqing', ) Yukong = CharacterList( - id=42, + id=45, name='Yukong', cn='驭空', cht='馭空', diff --git a/tasks/character/keywords/classes.py b/tasks/character/keywords/classes.py index cc4b1a37d..69e0cfd95 100644 --- a/tasks/character/keywords/classes.py +++ b/tasks/character/keywords/classes.py @@ -25,3 +25,11 @@ class CharacterList(Keyword): """ from tasks.character.keywords.height import CHARACTER_HEIGHT return CHARACTER_HEIGHT.get(self.name, 'Unknown') + + +@dataclass(repr=False) +class CombatType(Keyword): + instances: ClassVar = {} + + def __hash__(self) -> int: + return super().__hash__() diff --git a/tasks/character/keywords/combat_type.py b/tasks/character/keywords/combat_type.py new file mode 100644 index 000000000..6aaa3d57e --- /dev/null +++ b/tasks/character/keywords/combat_type.py @@ -0,0 +1,68 @@ +from .classes import CombatType + +# This file was auto-generated, do not modify it manually. To generate: +# ``` python -m dev_tools.keyword_extract ``` + +Physical = CombatType( + id=1, + name='Physical', + cn='物理', + cht='物理', + en='Physical', + jp='物理', + es='Físico', +) +Fire = CombatType( + id=2, + name='Fire', + cn='火', + cht='火', + en='Fire', + jp='炎', + es='Fuego', +) +Ice = CombatType( + id=3, + name='Ice', + cn='冰', + cht='冰', + en='Ice', + jp='氷', + es='Hielo', +) +Lightning = CombatType( + id=4, + name='Lightning', + cn='雷', + cht='雷', + en='Lightning', + jp='雷', + es='Rayo', +) +Wind = CombatType( + id=5, + name='Wind', + cn='风', + cht='風', + en='Wind', + jp='風', + es='Viento', +) +Quantum = CombatType( + id=6, + name='Quantum', + cn='量子', + cht='量子', + en='Quantum', + jp='量子', + es='Cuántico', +) +Imaginary = CombatType( + id=7, + name='Imaginary', + cn='虚数', + cht='虛數', + en='Imaginary', + jp='虚数', + es='Imaginario', +) diff --git a/tasks/character/switch.py b/tasks/character/switch.py index 1cef0a69a..4240a9309 100644 --- a/tasks/character/switch.py +++ b/tasks/character/switch.py @@ -1,4 +1,5 @@ import re +import typing as t import cv2 import numpy as np @@ -10,7 +11,7 @@ from module.logger import logger from module.ocr.ocr import BoxedResult, OcrResultButton, OcrWhiteLetterOnComplexBackground from tasks.base.ui import UI from tasks.character.assets.assets_character_switch import * -from tasks.character.keywords import CharacterList, DICT_SORTED_RANGES, KEYWORD_CHARACTER_LIST +from tasks.character.keywords import CharacterList, DICT_SORTED_RANGES, KEYWORDS_CHARACTER_LIST class OcrCharacterName(OcrWhiteLetterOnComplexBackground): @@ -22,6 +23,8 @@ class OcrCharacterName(OcrWhiteLetterOnComplexBackground): # Dan Heng o.ImbibitorLunae result = re.sub(r'[0Oo\-. ]{1,3}Imbi', 'Imbi', result) + result = re.sub(r'院.?梅', '阮•梅', result) + return super().after_process(result) @@ -52,13 +55,18 @@ class CharacterSwitch(UI): logger.warning('Character update timeout') break + # Ocr names ocr = OcrCharacterName(OCR_MAP_CHARACTERS) buttons = ocr.matched_ocr(self.device.image, keyword_classes=CharacterList) - if trailblazer := self._get_character_trailblazer(): - buttons.append(trailblazer) + # Add avatars + characters = [button.matched_keyword for button in buttons] + for trailblazer in self._iter_character_by_avatar(): + if trailblazer.matched_keyword not in characters: + buttons.append(trailblazer) + + # Set properties buttons = sorted(buttons, key=lambda b: area_center(b.area)[1]) self.character_buttons = buttons - self.characters = [button.matched_keyword for button in self.character_buttons] logger.attr('Characters', self.characters) self.character_current = self._convert_selected_to_character(self._update_current_character()) @@ -75,28 +83,33 @@ class CharacterSwitch(UI): return self.characters - def _get_character_trailblazer(self) -> OcrResultButton | None: + def _iter_character_by_avatar(self) -> t.Iterable[OcrResultButton]: + """ + Detect characters that can't be found by OCR + """ dict_template = { - KEYWORD_CHARACTER_LIST.TrailblazerDestruction: [ + KEYWORDS_CHARACTER_LIST.TrailblazerDestruction: [ TrailblazerDestructionMale, TrailblazerDestructionFemale, ], - KEYWORD_CHARACTER_LIST.TrailblazerPreservation: [ + KEYWORDS_CHARACTER_LIST.TrailblazerPreservation: [ TrailblazerPreservationMale, TrailblazerPreservationFemale, ], + KEYWORDS_CHARACTER_LIST.Huohuo: [ + Huohuo, + ], } for character, templates in dict_template.items(): for template in templates: template.load_search(TRAILBLAZER_SEARCH.area) if template.match_template(self.device.image): - logger.info(f'Found trailblazer: {template}') + logger.info(f'Found avatar {template}') # Create a fake OcrResultButton object box = BoxedResult(box=template.button, text_img=None, ocr_text='', score=1.0) button = OcrResultButton(boxed_result=box, matched_keyword=character) - return button - return None + yield button def _update_current_character(self) -> list[int]: """ diff --git a/tasks/combat/assets/assets_combat_interact.py b/tasks/combat/assets/assets_combat_interact.py index 790440071..c122037bc 100644 --- a/tasks/combat/assets/assets_combat_interact.py +++ b/tasks/combat/assets/assets_combat_interact.py @@ -5,13 +5,22 @@ from module.base.button import Button, ButtonWrapper DUNGEON_COMBAT_INTERACT = ButtonWrapper( name='DUNGEON_COMBAT_INTERACT', - share=Button( - file='./assets/share/combat/interact/DUNGEON_COMBAT_INTERACT.png', - area=(753, 419, 781, 441), - search=(733, 399, 801, 461), - color=(199, 197, 198), - button=(750, 411, 997, 448), - ), + share=[ + Button( + file='./assets/share/combat/interact/DUNGEON_COMBAT_INTERACT.png', + area=(753, 419, 781, 441), + search=(733, 399, 801, 461), + color=(199, 197, 198), + button=(750, 411, 997, 448), + ), + Button( + file='./assets/share/combat/interact/DUNGEON_COMBAT_INTERACT.2.png', + area=(780, 419, 808, 441), + search=(760, 399, 828, 461), + color=(199, 197, 198), + button=(750, 411, 997, 448), + ), + ], ) DUNGEON_COMBAT_INTERACT_TEXT = ButtonWrapper( name='DUNGEON_COMBAT_INTERACT_TEXT', @@ -28,7 +37,7 @@ MAP_LOADING = ButtonWrapper( share=Button( file='./assets/share/combat/interact/MAP_LOADING.png', area=(644, 367, 662, 389), - search=(639, 347, 667, 394), + search=(639, 357, 667, 405), color=(159, 141, 149), button=(644, 367, 662, 389), ), diff --git a/tasks/combat/assets/assets_combat_state.py b/tasks/combat/assets/assets_combat_state.py index a21444b19..043fb6029 100644 --- a/tasks/combat/assets/assets_combat_state.py +++ b/tasks/combat/assets/assets_combat_state.py @@ -10,7 +10,7 @@ COMBAT_AUTO = ButtonWrapper( area=(1113, 22, 1183, 58), search=(1093, 2, 1203, 78), color=(135, 137, 131), - button=(1113, 22, 1183, 58), + button=(1136, 31, 1161, 49), ), ) COMBAT_PAUSE = ButtonWrapper( @@ -30,6 +30,6 @@ COMBAT_SPEED_2X = ButtonWrapper( area=(1029, 22, 1099, 58), search=(1009, 2, 1119, 78), color=(138, 143, 146), - button=(1029, 22, 1099, 58), + button=(1047, 29, 1079, 49), ), ) diff --git a/tasks/combat/assets/assets_combat_support.py b/tasks/combat/assets/assets_combat_support.py index c5a3d4ecd..10dc25671 100644 --- a/tasks/combat/assets/assets_combat_support.py +++ b/tasks/combat/assets/assets_combat_support.py @@ -7,40 +7,40 @@ COMBAT_SUPPORT_ADD = ButtonWrapper( name='COMBAT_SUPPORT_ADD', share=Button( file='./assets/share/combat/support/COMBAT_SUPPORT_ADD.png', - area=(1032, 649, 1132, 680), - search=(1012, 629, 1152, 700), - color=(228, 228, 228), - button=(1032, 649, 1132, 680), + area=(1057, 649, 1112, 678), + search=(1037, 629, 1132, 698), + color=(213, 214, 214), + button=(1057, 649, 1112, 678), ), ) COMBAT_SUPPORT_LIST = ButtonWrapper( name='COMBAT_SUPPORT_LIST', share=Button( file='./assets/share/combat/support/COMBAT_SUPPORT_LIST.png', - area=(57, 637, 100, 680), - search=(37, 617, 120, 700), - color=(212, 213, 215), - button=(57, 637, 100, 680), + area=(67, 645, 93, 669), + search=(47, 625, 113, 689), + color=(204, 205, 205), + button=(67, 645, 93, 669), ), ) COMBAT_SUPPORT_LIST_GRID = ButtonWrapper( name='COMBAT_SUPPORT_LIST_GRID', share=Button( file='./assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png', - area=(64, 115, 159, 634), - search=(44, 95, 179, 654), - color=(119, 108, 132), - button=(64, 115, 159, 634), + area=(64, 158, 155, 627), + search=(44, 138, 175, 647), + color=(117, 107, 124), + button=(64, 158, 155, 627), ), ) COMBAT_SUPPORT_LIST_SCROLL = ButtonWrapper( name='COMBAT_SUPPORT_LIST_SCROLL', share=Button( file='./assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png', - area=(448, 112, 452, 610), - search=(428, 92, 472, 630), - color=(127, 133, 150), - button=(448, 112, 452, 610), + area=(448, 156, 452, 592), + search=(428, 136, 472, 612), + color=(130, 133, 153), + button=(448, 156, 452, 592), ), ) COMBAT_SUPPORT_SELECTED = ButtonWrapper( @@ -53,3 +53,36 @@ COMBAT_SUPPORT_SELECTED = ButtonWrapper( button=(69, 114, 91, 116), ), ) +SUPPORT_SELECTED = ButtonWrapper( + name='SUPPORT_SELECTED', + share=[ + Button( + file='./assets/share/combat/support/SUPPORT_SELECTED.png', + area=(54, 202, 60, 220), + search=(40, 146, 68, 628), + color=(125, 126, 131), + button=(54, 202, 60, 220), + ), + Button( + file='./assets/share/combat/support/SUPPORT_SELECTED.2.png', + area=(53, 547, 59, 565), + search=(40, 146, 68, 628), + color=(144, 146, 147), + button=(53, 547, 59, 565), + ), + Button( + file='./assets/share/combat/support/SUPPORT_SELECTED.3.png', + area=(54, 432, 61, 450), + search=(40, 146, 68, 628), + color=(139, 139, 141), + button=(54, 432, 61, 450), + ), + Button( + file='./assets/share/combat/support/SUPPORT_SELECTED.4.png', + area=(52, 417, 59, 435), + search=(40, 146, 68, 628), + color=(140, 138, 145), + button=(52, 417, 59, 435), + ), + ], +) diff --git a/tasks/combat/combat.py b/tasks/combat/combat.py index 3ba806dad..ab97419ce 100644 --- a/tasks/combat/combat.py +++ b/tasks/combat/combat.py @@ -1,4 +1,5 @@ from module.base.decorator import run_once +from module.exception import RequestHumanTakeover from module.logger import logger from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE @@ -81,6 +82,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo logger.hr('Combat prepare') skip_first_screenshot = True pre_set_team = bool(support_character) + trial = 0 while 1: if skip_first_screenshot: skip_first_screenshot = False @@ -90,6 +92,11 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo # End if self.is_combat_executing(): return True + # Relics full + # Clicking between COMBAT_PREPARE and COMBAT_TEAM_PREPARE + if trial > 3: + logger.critical('Failed to enter dungeon after 3 trial, probably because relics are full') + raise RequestHumanTakeover # Click if self.appear(COMBAT_TEAM_SUPPORT) and support_character: @@ -112,6 +119,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo return False self.device.click(COMBAT_PREPARE) self.interval_reset(COMBAT_PREPARE) + trial += 1 continue if self.handle_combat_interact(): continue @@ -257,8 +265,12 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo self.device.click(COMBAT_EXIT) self.interval_reset(COMBAT_AGAIN) continue + # Dropped light cone from weekly if self.handle_get_light_cone(): continue + # Having any character died + if self.handle_popup_confirm(): + continue def combat_exit(self, skip_first_screenshot=True): """ @@ -308,6 +320,9 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo Returns: int: Run count + Raises: + RequestHumanTakeover: If relics are full + Pages: in: COMBAT_PREPARE or page_main with DUNGEON_COMBAT_INTERACT diff --git a/tasks/combat/state.py b/tasks/combat/state.py index ed11c418f..3884a94a9 100644 --- a/tasks/combat/state.py +++ b/tasks/combat/state.py @@ -67,7 +67,8 @@ class CombatState(UI): return False if not self.is_combat_executing(): if not self._combat_auto_checked and auto: - if self._combat_click_interval.started() and not self._combat_click_interval.reached(): + # >=0.2s after clicking the button to avoid random noice + if self._combat_click_interval.current() >= 0.15 and not self._combat_click_interval.reached(): logger.info('Combat on going, _combat_auto_checked') self._combat_auto_checked = True return False diff --git a/tasks/combat/support.py b/tasks/combat/support.py index 57f0c86df..ff628217d 100644 --- a/tasks/combat/support.py +++ b/tasks/combat/support.py @@ -1,17 +1,17 @@ import cv2 import numpy as np from scipy import signal -from module.base.button import Button, ButtonWrapper +from module.base.button import ClickButton from module.base.timer import Timer -from module.base.utils import area_size, crop, rgb2luma, load_image, crop +from module.base.utils import area_offset, area_size, crop, load_image, rgb2luma from module.logger import logger from module.ui.scroll import Scroll from tasks.base.assets.assets_base_popup import POPUP_CANCEL from tasks.base.ui import UI from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST, \ - COMBAT_SUPPORT_LIST_SCROLL, COMBAT_SUPPORT_SELECTED, COMBAT_SUPPORT_LIST_GRID -from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_SUPPORT, COMBAT_TEAM_DISMISSSUPPORT + COMBAT_SUPPORT_LIST_GRID, COMBAT_SUPPORT_LIST_SCROLL, COMBAT_SUPPORT_SELECTED, SUPPORT_SELECTED +from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_DISMISSSUPPORT, COMBAT_TEAM_SUPPORT def get_position_in_original_image(position_in_croped_image, crop_area): @@ -55,7 +55,7 @@ class SupportCharacter: return SupportCharacter._image_cache[self.name] img = load_image(f"assets/character/{self.name}.png") - scaled_img = cv2.resize(img, (85, 82)) + scaled_img = cv2.resize(img, (86, 81)) SupportCharacter._image_cache[self.name] = scaled_img logger.info(f"Character {self.name} image cached") return scaled_img @@ -84,64 +84,36 @@ class SupportCharacter: self.button[0], self.button[1] - 5, self.button[0] + 30, self.button[1]) if self.button else None -class ArrowWrapper(ButtonWrapper): - - def find_center(self, image): - res = cv2.matchTemplate( - self.matched_button.image, image, cv2.TM_CCOEFF_NORMED) - _, max_val, _, max_loc = cv2.minMaxLoc(res) - return ( - ( - (max_loc[0] + self.matched_button.image.shape[1] / 2), - (max_loc[1] + self.matched_button.image.shape[0] / 2), - ) - if max_val > 0.75 - else None - ) - - class NextSupportCharacter: - _arrow = ArrowWrapper( - name="NextSupportCharacterArrow", - share=Button( - file='./assets/support/selected_character_arrow.png', - area=None, - search=None, - color=None, - button=None, - ) - ) - _crop_area = (290, 115, 435, 634) - def __init__(self, screenshot): - self.name = "SupportCharacterArrow" - self.screenshot = crop(screenshot, NextSupportCharacter._crop_area) - self.arrow_center = self._find_center() - self.button = self._get_next_support_character_button() + self.name = "NextSupportCharacter" + self.button = self.get_next_support_character_button(screenshot) def __bool__(self): return self.button is not None - def _find_center(self): - center = NextSupportCharacter._arrow.find_center(self.screenshot) - center = get_position_in_original_image( - center, NextSupportCharacter._crop_area) if center else None - return center + def get_next_support_character_button(self, screenshot) -> ClickButton | None: + if SUPPORT_SELECTED.match_template(screenshot, similarity=0.75): + # Move area to the next character card center + area = SUPPORT_SELECTED.button + area = area_offset((105, 85, 255, 170), offset=area[:2]) + if area[3] < COMBAT_SUPPORT_LIST_GRID.area[3]: + return ClickButton(area, name=self.name) + else: + # Out of list + logger.info('Next character is out of list') + return None + else: + return None - def _get_next_support_character_button(self): - area = (self.arrow_center[0] - 200, min(self.arrow_center[1] + 65, 615), self.arrow_center[0] + 10, min( - self.arrow_center[1] + 80, 620)) if self.arrow_center and self.arrow_center[1] < 510 else None - return ButtonWrapper( - name="NextSupportCharacterButton", - share=Button( - file='./assets/support/selected_character_arrow.png', - area=area, - search=area, - # if next support was selected, the average color of the button will larger than 220 - color=(220, 220, 220), - button=area, - ) - ) if self.arrow_center and self.arrow_center[1] < 510 else None + def is_next_support_character_selected(self, screenshot) -> bool: + if self.button is None: + return False + area = self.button.area + # Move area from the card center to the left edge of the card + area = area_offset(area, offset=(-120, 0)) + image = crop(screenshot, area, copy=False) + return SUPPORT_SELECTED.match_template(image, similarity=0.75, direct_match=True) class SupportListScroll(Scroll): @@ -301,7 +273,7 @@ class CombatSupport(UI): self.device.screenshot() # End - if self.match_template(COMBAT_SUPPORT_SELECTED): + if self.appear(COMBAT_SUPPORT_SELECTED, similarity=0.75): return True if interval.reached(): @@ -351,7 +323,7 @@ class CombatSupport(UI): self.device.screenshot() # End - if next_support and self._next_support_selected(next_support): + if next_support is not None and next_support.is_next_support_character_selected(self.device.image): return if interval.reached(): @@ -367,13 +339,3 @@ class CombatSupport(UI): interval.reset() continue - - def _next_support_selected(self, next_support: NextSupportCharacter): - """ - Returns: - bool: True if selected else False - """ - if self.match_color(next_support.button, threshold=20): - logger.info("Next support selected") - return True - return False diff --git a/tasks/daily/daily_quest.py b/tasks/daily/daily_quest.py index 3e80a4798..d10953647 100644 --- a/tasks/daily/daily_quest.py +++ b/tasks/daily/daily_quest.py @@ -6,7 +6,6 @@ from module.base.utils import crop from module.logger import logger from module.ocr.ocr import Ocr, OcrResultButton from module.ocr.utils import split_and_pair_buttons -from tasks.battle_pass.keywords import KEYWORD_BATTLE_PASS_QUEST from tasks.daily.assets.assets_daily_reward import * from tasks.daily.camera import CameraUI from tasks.daily.keywords import ( @@ -337,7 +336,7 @@ class DailyQuestUI(DungeonUI, RouteLoader): # but battle pass quests need synthesizing consumables. # if self.synthesized_material: # quests = self.config.stored.BattlePassWeeklyQuest.load_quests() - # if KEYWORD_BATTLE_PASS_QUEST.Synthesize_Consumables_1_times in quests: + # if KEYWORDS_BATTLE_PASS_QUEST.Synthesize_Consumables_1_times in quests: # logger.info('Done weekly quest Synthesize_Consumables_1_times once') # self.config.stored.BattlePassQuestSynthesizeConsumables.add() # if self.config.stored.BattlePassQuestSynthesizeConsumables.is_full(): diff --git a/tasks/dungeon/assets/assets_dungeon_event.py b/tasks/dungeon/assets/assets_dungeon_event.py index d44033118..ca29c1110 100644 --- a/tasks/dungeon/assets/assets_dungeon_event.py +++ b/tasks/dungeon/assets/assets_dungeon_event.py @@ -37,10 +37,10 @@ OCR_DOUBLE_EVENT_REMAIN = ButtonWrapper( name='OCR_DOUBLE_EVENT_REMAIN', share=Button( file='./assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png', - area=(523, 181, 1087, 203), - search=(503, 161, 1107, 223), - color=(200, 162, 88), - button=(523, 181, 1087, 203), + area=(513, 181, 1103, 203), + search=(493, 161, 1123, 223), + color=(201, 164, 88), + button=(513, 181, 1103, 203), ), ) OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT = ButtonWrapper( diff --git a/tasks/dungeon/assets/assets_dungeon_ui.py b/tasks/dungeon/assets/assets_dungeon_ui.py index b4f0b1d11..d70a8e5b3 100644 --- a/tasks/dungeon/assets/assets_dungeon_ui.py +++ b/tasks/dungeon/assets/assets_dungeon_ui.py @@ -3,6 +3,36 @@ 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 ``` +CALYX_WORLD_1 = ButtonWrapper( + name='CALYX_WORLD_1', + share=Button( + file='./assets/share/dungeon/ui/CALYX_WORLD_1.png', + area=(490, 185, 540, 230), + search=(470, 165, 560, 250), + color=(197, 196, 196), + button=(490, 185, 540, 230), + ), +) +CALYX_WORLD_2 = ButtonWrapper( + name='CALYX_WORLD_2', + share=Button( + file='./assets/share/dungeon/ui/CALYX_WORLD_2.png', + area=(590, 185, 640, 230), + search=(570, 165, 660, 250), + color=(199, 198, 198), + button=(590, 185, 640, 230), + ), +) +CALYX_WORLD_3 = ButtonWrapper( + name='CALYX_WORLD_3', + share=Button( + file='./assets/share/dungeon/ui/CALYX_WORLD_3.png', + area=(689, 186, 739, 231), + search=(669, 166, 759, 251), + color=(158, 158, 158), + button=(689, 186, 739, 231), + ), +) DAILY_TRAINING_CHECK = ButtonWrapper( name='DAILY_TRAINING_CHECK', share=Button( @@ -33,6 +63,16 @@ DAILY_TRAINING_LOADED = ButtonWrapper( button=(1143, 546, 1158, 561), ), ) +LIST_LOADED_CHECK = ButtonWrapper( + name='LIST_LOADED_CHECK', + share=Button( + file='./assets/share/dungeon/ui/LIST_LOADED_CHECK.png', + area=(576, 606, 951, 664), + search=(556, 586, 971, 684), + color=(180, 188, 195), + button=(576, 606, 951, 664), + ), +) OCR_DUNGEON_LIST = ButtonWrapper( name='OCR_DUNGEON_LIST', share=Button( @@ -137,9 +177,19 @@ TREASURES_LIGHTWARD_LOADED = ButtonWrapper( name='TREASURES_LIGHTWARD_LOADED', share=Button( file='./assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.png', - area=(1029, 288, 1047, 306), - search=(1024, 283, 1052, 311), - color=(149, 149, 152), - button=(1029, 288, 1047, 306), + area=(1028, 288, 1048, 308), + search=(1008, 268, 1068, 328), + color=(82, 80, 80), + button=(1028, 288, 1048, 308), + ), +) +TREASURES_LIGHTWARD_LOCKED = ButtonWrapper( + name='TREASURES_LIGHTWARD_LOCKED', + share=Button( + file='./assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOCKED.png', + area=(789, 423, 817, 457), + search=(769, 403, 837, 477), + color=(112, 112, 112), + button=(789, 423, 817, 457), ), ) diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index 10afe2bae..6c7e5a60a 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -1,10 +1,10 @@ from module.base.utils import area_offset from module.logger import logger -from tasks.battle_pass.keywords import KEYWORD_BATTLE_PASS_QUEST +from tasks.battle_pass.keywords import KEYWORDS_BATTLE_PASS_QUEST from tasks.combat.combat import Combat from tasks.daily.keywords import KEYWORDS_DAILY_QUEST from tasks.dungeon.event import DungeonEvent -from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_DUNGEON_TAB +from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_DUNGEON_NAV, KEYWORDS_DUNGEON_TAB from tasks.dungeon.stamina import DungeonStamina @@ -84,7 +84,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if KEYWORDS_DAILY_QUEST.Clear_Calyx_Golden_1_times in self.daily_quests: logger.info('Achieved daily quest Clear_Calyx_Golden_1_times') self.achieved_daily_quest = True - if KEYWORD_BATTLE_PASS_QUEST.Clear_Calyx_1_times in self.weekly_quests: + if KEYWORDS_BATTLE_PASS_QUEST.Clear_Calyx_1_times in self.weekly_quests: logger.info('Done weekly quest Clear_Calyx_1_times once') self.config.stored.BattlePassQuestCalyx.add() if self.config.stored.BattlePassQuestCalyx.is_full(): @@ -95,7 +95,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if KEYWORDS_DAILY_QUEST.Clear_Calyx_Crimson_1_times in self.daily_quests: logger.info('Achieve daily quest Clear_Calyx_Crimson_1_times') self.achieved_daily_quest = True - if KEYWORD_BATTLE_PASS_QUEST.Clear_Calyx_1_times in self.weekly_quests: + if KEYWORDS_BATTLE_PASS_QUEST.Clear_Calyx_1_times in self.weekly_quests: logger.info('Done weekly quest Clear_Calyx_1_times once') self.config.stored.BattlePassQuestCalyx.add() if self.config.stored.BattlePassQuestCalyx.is_full(): @@ -111,7 +111,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if KEYWORDS_DAILY_QUEST.Clear_Cavern_of_Corrosion_1_times in self.daily_quests: logger.info('Achieve daily quest Clear_Cavern_of_Corrosion_1_times') self.achieved_daily_quest = True - if KEYWORD_BATTLE_PASS_QUEST.Clear_Cavern_of_Corrosion_1_times in self.weekly_quests: + if KEYWORDS_BATTLE_PASS_QUEST.Clear_Cavern_of_Corrosion_1_times in self.weekly_quests: logger.info('Done weekly quest Clear_Cavern_of_Corrosion_1_times once') self.config.stored.BattlePassQuestCavernOfCorrosion.add() if self.config.stored.BattlePassQuestCavernOfCorrosion.is_full(): @@ -122,7 +122,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if KEYWORDS_DAILY_QUEST.Complete_Echo_of_War_1_times in self.daily_quests: logger.info('Achieve daily quest Complete_Echo_of_War_1_times') self.achieved_daily_quest = True - if KEYWORD_BATTLE_PASS_QUEST.Complete_Echo_of_War_1_times in self.weekly_quests: + if KEYWORDS_BATTLE_PASS_QUEST.Complete_Echo_of_War_1_times in self.weekly_quests: logger.info('Done weekly quest Complete_Echo_of_War_1_times once') self.config.stored.BattlePassQuestEchoOfWar.add() if self.config.stored.BattlePassQuestEchoOfWar.is_full(): @@ -211,10 +211,10 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if self.has_double_rogue_event(): rogue = self.get_double_event_remain() if self.has_double_calyx_event(): - self._dungeon_nav_goto(KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures) + self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Calyx_Golden) calyx = self.get_double_event_remain() if self.has_double_relic_event(): - self._dungeon_nav_goto(KEYWORDS_DUNGEON_LIST.Cavern_of_Corrosion_Path_of_Gelid_Wind) + self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion) relic = self.get_double_event_remain() with self.config.multi_set(): self.config.stored.DungeonDouble.calyx = calyx @@ -405,11 +405,15 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): return require def check_stamina_quest(self, stamina_used: int): - if KEYWORD_BATTLE_PASS_QUEST.Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max not in self.weekly_quests: - return + logger.info(f'Used {stamina_used} stamina') - logger.info(f'Done Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max stamina {stamina_used}') - self.config.stored.BattlePassQuestTrailblazePower.add(stamina_used) - if self.config.stored.BattlePassQuestTrailblazePower.is_full(): - logger.info('Achieved weekly quest Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max') - self.achieved_weekly_quest = True + if KEYWORDS_BATTLE_PASS_QUEST.Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max in self.weekly_quests: + logger.info(f'Done Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max stamina {stamina_used}') + self.config.stored.BattlePassQuestTrailblazePower.add(stamina_used) + if self.config.stored.BattlePassQuestTrailblazePower.is_full(): + logger.info('Achieved weekly quest Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max') + self.achieved_weekly_quest = True + + if KEYWORDS_DAILY_QUEST.Consume_120_Trailblaze_Power in self.daily_quests: + logger.info(f'Done Consume_120_Trailblaze_Power stamina {stamina_used}') + self.achieved_daily_quest = True diff --git a/tasks/dungeon/keywords/classes.py b/tasks/dungeon/keywords/classes.py index c531cf4cb..88bccc895 100644 --- a/tasks/dungeon/keywords/classes.py +++ b/tasks/dungeon/keywords/classes.py @@ -20,14 +20,64 @@ class DungeonTab(Keyword): class DungeonList(Keyword): instances: ClassVar = {} + plane_id: int + + @cached_property + def plane(self): + """ + Returns: + MapPlane: MapPlane object or None + """ + from tasks.map.keywords import MapPlane + return MapPlane.find_plane_id(self.plane_id) + + @cached_property + def world(self): + """ + Returns: + MapWorld: MapWorld object or None + """ + if self.plane is not None: + return self.plane.world + else: + return None + @cached_property def is_Calyx_Golden(self): return 'Calyx_Golden' in self.name + @cached_property + def is_Calyx_Golden_Memories(self): + return 'Calyx_Golden_Memories' in self.name + + @cached_property + def is_Calyx_Golden_Aether(self): + return 'Calyx_Golden_Aether' in self.name + + @cached_property + def is_Calyx_Golden_Treasures(self): + return 'Calyx_Golden_Treasures' in self.name + @cached_property def is_Calyx_Crimson(self): return 'Calyx_Crimson' in self.name + @cached_property + def Calyx_Crimson_Path(self): + """ + Returns: + RoguePath: RoguePath object or None + """ + if not self.is_Calyx_Crimson: + return None + from tasks.rogue.keywords import RoguePath + for path in RoguePath.instances.values(): + if path.name in self.name: + return path + elif path.name == 'The_Harmony' and 'Harmony' in self.name: + return path + return None + @cached_property def is_Calyx(self): return self.is_Calyx_Golden or self.is_Calyx_Crimson @@ -36,6 +86,24 @@ class DungeonList(Keyword): def is_Stagnant_Shadow(self): return 'Stagnant_Shadow' in self.name + @cached_property + def Stagnant_Shadow_Combat_Type(self): + """ + Returns: + CombatType: CombatType object or None + """ + if not self.is_Stagnant_Shadow: + return None + from tasks.dungeon.keywords import DungeonDetailed + detail = DungeonDetailed.find_name(self.name) + if detail is None: + return None + from tasks.character.keywords import CombatType + for type_ in CombatType.instances.values(): + if type_.cn in detail.cn[:10]: + return type_ + return None + @cached_property def is_Cavern_of_Corrosion(self): return 'Cavern_of_Corrosion' in self.name diff --git a/tasks/dungeon/keywords/dungeon.py b/tasks/dungeon/keywords/dungeon.py index 4ff0259c4..52ef19cf1 100644 --- a/tasks/dungeon/keywords/dungeon.py +++ b/tasks/dungeon/keywords/dungeon.py @@ -3,435 +3,603 @@ from .classes import DungeonList # This file was auto-generated, do not modify it manually. To generate: # ``` python -m dev_tools.keyword_extract ``` -Calyx_Golden_Memories = DungeonList( +Calyx_Golden_Memories_Jarilo_VI = DungeonList( id=1, - name='Calyx_Golden_Memories', - cn='回忆之蕾•拟造花萼(金)', - cht='回憶之蕾•擬造花萼(金)', - en='Bud of Memories', - jp='疑似花萼(金)・回憶の蕾', - es='Flor de los recuerdos', + name='Calyx_Golden_Memories_Jarilo_VI', + cn='回忆之蕾•雅利洛-Ⅵ', + cht='回憶之蕾•雅利洛-Ⅵ', + en='Bud of Memories (Jarilo-Ⅵ)', + jp='回憶の蕾・ヤリーロ-Ⅵ', + es='Flor de los recuerdos (Jarilo-Ⅵ)', + plane_id=2010101, ) -Calyx_Golden_Aether = DungeonList( +Calyx_Golden_Aether_Jarilo_VI = DungeonList( id=2, - name='Calyx_Golden_Aether', - cn='以太之蕾•拟造花萼(金)', - cht='乙太之蕾•擬造花萼(金)', - en='Bud of Aether', - jp='疑似花萼(金)・エーテルの蕾', - es='Flor de éter', + name='Calyx_Golden_Aether_Jarilo_VI', + cn='以太之蕾•雅利洛-Ⅵ', + cht='乙太之蕾•雅利洛-Ⅵ', + en='Bud of Aether (Jarilo-Ⅵ)', + jp='エーテルの蕾・ヤリーロ-Ⅵ', + es='Flor de éter (Jarilo-Ⅵ)', + plane_id=2011101, ) -Calyx_Golden_Treasures = DungeonList( +Calyx_Golden_Treasures_Jarilo_VI = DungeonList( id=3, - name='Calyx_Golden_Treasures', - cn='藏珍之蕾•拟造花萼(金)', - cht='藏珍之蕾•擬造花萼(金)', - en='Bud of Treasures', - jp='疑似花萼(金)・秘蔵の蕾', - es='Flor de tesoros', + name='Calyx_Golden_Treasures_Jarilo_VI', + cn='藏珍之蕾•雅利洛-Ⅵ', + cht='藏珍之蕾•雅利洛-Ⅵ', + en='Bud of Treasures (Jarilo-Ⅵ)', + jp='秘蔵の蕾・ヤリーロ-Ⅵ', + es='Flor de tesoros (Jarilo-Ⅵ)', + plane_id=2012101, ) -Calyx_Crimson_Destruction = DungeonList( +Calyx_Golden_Memories_The_Xianzhou_Luofu = DungeonList( id=4, - name='Calyx_Crimson_Destruction', + name='Calyx_Golden_Memories_The_Xianzhou_Luofu', + cn='回忆之蕾•仙舟「罗浮」', + cht='回憶之蕾•仙舟「羅浮」', + en='Bud of Memories (The Xianzhou Luofu)', + jp='回憶の蕾・仙舟「羅浮」', + es='Flor de los recuerdos (El Luofu de Xianzhou)', + plane_id=2021101, +) +Calyx_Golden_Aether_The_Xianzhou_Luofu = DungeonList( + id=5, + name='Calyx_Golden_Aether_The_Xianzhou_Luofu', + cn='以太之蕾•仙舟「罗浮」', + cht='乙太之蕾•仙舟「羅浮」', + en='Bud of Aether (The Xianzhou Luofu)', + jp='エーテルの蕾・仙舟「羅浮」', + es='Flor de éter (El Luofu de Xianzhou)', + plane_id=2022101, +) +Calyx_Golden_Treasures_The_Xianzhou_Luofu = DungeonList( + id=6, + name='Calyx_Golden_Treasures_The_Xianzhou_Luofu', + cn='藏珍之蕾•仙舟「罗浮」', + cht='藏珍之蕾•仙舟「羅浮」', + en='Bud of Treasures (The Xianzhou Luofu)', + jp='秘蔵の蕾・仙舟「羅浮」', + es='Flor de tesoros (El Luofu de Xianzhou)', + plane_id=2022201, +) +Calyx_Golden_Memories_Penacony = DungeonList( + id=7, + name='Calyx_Golden_Memories_Penacony', + cn='回忆之蕾•匹诺康尼', + cht='回憶之蕾•匹諾康尼', + en='Bud of Memories (Penacony)', + jp='回憶の蕾・ピノコニー', + es='Flor de los recuerdos (Colonipenal)', + plane_id=2031301, +) +Calyx_Golden_Aether_Penacony = DungeonList( + id=8, + name='Calyx_Golden_Aether_Penacony', + cn='以太之蕾•匹诺康尼', + cht='乙太之蕾•匹諾康尼', + en='Bud of Aether (Penacony)', + jp='エーテルの蕾・ピノコニー', + es='Flor de éter (Colonipenal)', + plane_id=2031201, +) +Calyx_Golden_Treasures_Penacony = DungeonList( + id=9, + name='Calyx_Golden_Treasures_Penacony', + cn='藏珍之蕾•匹诺康尼', + cht='藏珍之蕾•匹諾康尼', + en='Bud of Treasures (Penacony)', + jp='秘蔵の蕾・ピノコニー', + es='Flor de tesoros (Colonipenal)', + plane_id=2031101, +) +Calyx_Crimson_Destruction_Herta_StorageZone = DungeonList( + id=10, + name='Calyx_Crimson_Destruction_Herta_StorageZone', cn='毁灭之蕾•拟造花萼(赤)', cht='毀滅之蕾•擬造花萼(赤)', en='Bud of Destruction', jp='疑似花萼(赤)・壊滅の蕾', es='Flor de la Destrucción', + plane_id=2000201, ) -Calyx_Crimson_Preservation = DungeonList( - id=5, - name='Calyx_Crimson_Preservation', +Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape = DungeonList( + id=11, + name='Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape', + cn='毁灭之蕾•拟造花萼(赤)', + cht='毀滅之蕾•擬造花萼(赤)', + en='Bud of Destruction', + jp='疑似花萼(赤)・壊滅の蕾', + es='Flor de la Destrucción', + plane_id=2023201, +) +Calyx_Crimson_Preservation_Herta_SupplyZone = DungeonList( + id=12, + name='Calyx_Crimson_Preservation_Herta_SupplyZone', cn='存护之蕾•拟造花萼(赤)', cht='存護之蕾•擬造花萼(赤)', en='Bud of Preservation', jp='疑似花萼(赤)・存護の蕾', es='Flor de la Conservación', + plane_id=2000301, ) -Calyx_Crimson_The_Hunt = DungeonList( - id=6, - name='Calyx_Crimson_The_Hunt', +Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains = DungeonList( + id=13, + name='Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains', cn='巡猎之蕾•拟造花萼(赤)', cht='巡獵之蕾•擬造花萼(赤)', en='Bud of The Hunt', jp='疑似花萼(赤)・巡狩の蕾', es='Flor de la Cacería', + plane_id=2010101, ) -Calyx_Crimson_Abundance = DungeonList( - id=7, - name='Calyx_Crimson_Abundance', +Calyx_Crimson_Abundance_Jarilo_BackwaterPass = DungeonList( + id=14, + name='Calyx_Crimson_Abundance_Jarilo_BackwaterPass', cn='丰饶之蕾•拟造花萼(赤)', cht='豐饒之蕾•擬造花萼(赤)', en='Bud of Abundance', jp='疑似花萼(赤)・豊穣の蕾', es='Flor de la Abundancia', + plane_id=2011101, ) -Calyx_Crimson_Erudition = DungeonList( - id=8, - name='Calyx_Crimson_Erudition', +Calyx_Crimson_Erudition_Jarilo_RivetTown = DungeonList( + id=15, + name='Calyx_Crimson_Erudition_Jarilo_RivetTown', cn='智识之蕾•拟造花萼(赤)', cht='智識之蕾•擬造花萼(赤)', en='Bud of Erudition', jp='疑似花萼(赤)・知恵の蕾', es='Flor de la Erudición', + plane_id=2012201, ) -Calyx_Crimson_Harmony = DungeonList( - id=9, - name='Calyx_Crimson_Harmony', +Calyx_Crimson_Harmony_Jarilo_RobotSettlement = DungeonList( + id=16, + name='Calyx_Crimson_Harmony_Jarilo_RobotSettlement', cn='同谐之蕾•拟造花萼(赤)', cht='同諧之蕾•擬造花萼(赤)', en='Bud of Harmony', jp='疑似花萼(赤)・調和の蕾', es='Flor de la Armonía', + plane_id=2012301, ) -Calyx_Crimson_Nihility = DungeonList( - id=10, - name='Calyx_Crimson_Nihility', +Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape = DungeonList( + id=17, + name='Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape', + cn='同谐之蕾•拟造花萼(赤)', + cht='同諧之蕾•擬造花萼(赤)', + en='Bud of Harmony', + jp='疑似花萼(赤)・調和の蕾', + es='Flor de la Armonía', + plane_id=2031101, +) +Calyx_Crimson_Nihility_Jarilo_GreatMine = DungeonList( + id=18, + name='Calyx_Crimson_Nihility_Jarilo_GreatMine', cn='虚无之蕾•拟造花萼(赤)', cht='虛無之蕾•擬造花萼(赤)', en='Bud of Nihility', jp='疑似花萼(赤)・虚無の蕾', es='Flor de la Nihilidad', + plane_id=2012101, +) +Calyx_Crimson_Nihility_Luofu_AlchemyCommission = DungeonList( + id=19, + name='Calyx_Crimson_Nihility_Luofu_AlchemyCommission', + cn='虚无之蕾•拟造花萼(赤)', + cht='虛無之蕾•擬造花萼(赤)', + en='Bud of Nihility', + jp='疑似花萼(赤)・虚無の蕾', + es='Flor de la Nihilidad', + plane_id=2023101, ) Stagnant_Shadow_Quanta = DungeonList( - id=11, + id=20, name='Stagnant_Shadow_Quanta', cn='空海之形•凝滞虚影', cht='空海之形•凝滯虛影', en='Shape of Quanta', jp='凝結虚影・虚海の形', es='Forma del cuanto', + plane_id=2000101, ) Stagnant_Shadow_Gust = DungeonList( - id=12, + id=21, name='Stagnant_Shadow_Gust', cn='巽风之形•凝滞虚影', cht='巽風之形•凝滯虛影', en='Shape of Gust', jp='凝結虚影・薫風の形', es='Forma del aire', + plane_id=2012201, ) Stagnant_Shadow_Fulmination = DungeonList( - id=13, + id=22, name='Stagnant_Shadow_Fulmination', cn='鸣雷之形•凝滞虚影', cht='鳴雷之形•凝滯虛影', en='Shape of Fulmination', jp='凝結虚影・鳴雷の形', es='Forma del trueno', + plane_id=2013201, ) Stagnant_Shadow_Blaze = DungeonList( - id=14, + id=23, name='Stagnant_Shadow_Blaze', cn='炎华之形•凝滞虚影', cht='炎華之形•凝滯虛影', en='Shape of Blaze', jp='凝結虚影・炎華の形', es='Forma de las llamas', + plane_id=2013101, ) Stagnant_Shadow_Spike = DungeonList( - id=15, + id=24, name='Stagnant_Shadow_Spike', cn='锋芒之形•凝滞虚影', cht='鋒芒之形•凝滯虛影', en='Shape of Spike', jp='凝結虚影・切先の形', es='Forma afilada', + plane_id=2012101, ) Stagnant_Shadow_Rime = DungeonList( - id=16, + id=25, name='Stagnant_Shadow_Rime', cn='霜晶之形•凝滞虚影', cht='霜晶之形•凝滯虛影', en='Shape of Rime', jp='凝結虚影・霜晶の形', es='Forma de la escarcha', + plane_id=2013201, ) Stagnant_Shadow_Mirage = DungeonList( - id=17, + id=26, name='Stagnant_Shadow_Mirage', cn='幻光之形•凝滞虚影', cht='幻光之形•凝滯虛影', en='Shape of Mirage', jp='凝結虚影・幻光の形', es='Forma del espejismo', + plane_id=2011101, ) Stagnant_Shadow_Icicle = DungeonList( - id=18, + id=27, name='Stagnant_Shadow_Icicle', cn='冰棱之形•凝滞虚影', cht='冰稜之形•凝滯虛影', en='Shape of Icicle', jp='凝結虚影・氷柱の形', es='Forma del témpano', + plane_id=2021101, ) Stagnant_Shadow_Doom = DungeonList( - id=19, + id=28, name='Stagnant_Shadow_Doom', cn='震厄之形•凝滞虚影', cht='震厄之形•凝滯虛影', en='Shape of Doom', jp='凝結虚影・震厄の形', es='Forma de la perdición', + plane_id=2021201, ) Stagnant_Shadow_Puppetry = DungeonList( - id=20, + id=29, name='Stagnant_Shadow_Puppetry', cn='偃偶之形•凝滞虚影', cht='偃偶之形•凝滯虛影', en='Shape of Puppetry', jp='凝結虚影・傀儡の形', es='Forma de las marionetas', + plane_id=2022201, ) Stagnant_Shadow_Abomination = DungeonList( - id=21, + id=30, name='Stagnant_Shadow_Abomination', cn='孽兽之形•凝滞虚影', cht='孽獸之形•凝滯虛影', en='Shape of Abomination', jp='凝結虚影・厄獣の形', es='Forma de la abominación', + plane_id=2023201, ) Stagnant_Shadow_Scorch = DungeonList( - id=22, + id=31, name='Stagnant_Shadow_Scorch', cn='燔灼之形•凝滞虚影', cht='燔灼之形•凝滯虛影', en='Shape of Scorch', jp='凝結虚影・燔灼の形', es='Forma abrasada', + plane_id=2012101, ) Stagnant_Shadow_Celestial = DungeonList( - id=23, + id=32, name='Stagnant_Shadow_Celestial', cn='天人之形•凝滞虚影', cht='天人之形•凝滯虛影', en='Shape of Celestial', jp='凝結虚影・天人の形', es='Forma de lo celestial', + plane_id=2023101, ) Stagnant_Shadow_Perdition = DungeonList( - id=24, + id=33, name='Stagnant_Shadow_Perdition', cn='幽府之形•凝滞虚影', cht='幽府之形•凝滯虛影', en='Shape of Perdition', jp='凝結虚影・幽府の形', es='Forma del aislamiento', + plane_id=2022301, +) +Stagnant_Shadow_Nectar = DungeonList( + id=34, + name='Stagnant_Shadow_Nectar', + cn='冰酿之形•凝滞虚影', + cht='冰釀之形•凝滯虛影', + en='Shape of Nectar', + jp='凝結虚影・氷醸の形', + es='Forma del néctar', + plane_id=2031101, +) +Stagnant_Shadow_Roast = DungeonList( + id=35, + name='Stagnant_Shadow_Roast', + cn='焦炙之形•凝滞虚影', + cht='焦炙之形•凝滯虛影', + en='Shape of Roast', + jp='凝結虚影・焦灼の形', + es='Forma del agostamiento', + plane_id=2031301, ) Cavern_of_Corrosion_Path_of_Gelid_Wind = DungeonList( - id=25, + id=36, name='Cavern_of_Corrosion_Path_of_Gelid_Wind', cn='霜风之径•侵蚀隧洞', cht='霜風之徑•侵蝕隧洞', en='Path of Gelid Wind', jp='侵蝕トンネル・霜風の路', es='Senda del viento gélido', + plane_id=2000201, ) Cavern_of_Corrosion_Path_of_Jabbing_Punch = DungeonList( - id=26, + id=37, name='Cavern_of_Corrosion_Path_of_Jabbing_Punch', cn='迅拳之径•侵蚀隧洞', cht='迅拳之徑•侵蝕隧洞', en='Path of Jabbing Punch', jp='侵蝕トンネル・迅拳の路', es='Senda de los puños rápidos', + plane_id=2013101, ) Cavern_of_Corrosion_Path_of_Drifting = DungeonList( - id=27, + id=38, name='Cavern_of_Corrosion_Path_of_Drifting', cn='漂泊之径•侵蚀隧洞', cht='漂泊之徑•侵蝕隧洞', en='Path of Drifting', jp='侵蝕トンネル・漂泊の路', es='Senda de la deriva', + plane_id=2013201, ) Cavern_of_Corrosion_Path_of_Providence = DungeonList( - id=28, + id=39, name='Cavern_of_Corrosion_Path_of_Providence', cn='睿治之径•侵蚀隧洞', cht='睿治之徑•侵蝕隧洞', en='Path of Providence', jp='侵蝕トンネル・睿治の路', es='Senda de la providencia', + plane_id=2013401, ) Cavern_of_Corrosion_Path_of_Holy_Hymn = DungeonList( - id=29, + id=40, name='Cavern_of_Corrosion_Path_of_Holy_Hymn', cn='圣颂之径•侵蚀隧洞', cht='聖頌之徑•侵蝕隧洞', en='Path of Holy Hymn', jp='侵蝕トンネル・聖頌の路', es='Senda del himno sagrado', + plane_id=2021101, ) Cavern_of_Corrosion_Path_of_Conflagration = DungeonList( - id=30, + id=41, name='Cavern_of_Corrosion_Path_of_Conflagration', cn='野焰之径•侵蚀隧洞', cht='野焰之徑•侵蝕隧洞', en='Path of Conflagration', jp='侵蝕トンネル・野焔の路', es='Senda de la conflagración', + plane_id=2021201, ) Cavern_of_Corrosion_Path_of_Elixir_Seekers = DungeonList( - id=31, + id=42, name='Cavern_of_Corrosion_Path_of_Elixir_Seekers', cn='药使之径•侵蚀隧洞', cht='藥使之徑•侵蝕隧洞', en='Path of Elixir Seekers', jp='侵蝕トンネル・薬使の路', es='Senda de los elixires', + plane_id=2023101, ) Cavern_of_Corrosion_Path_of_Darkness = DungeonList( - id=32, + id=43, name='Cavern_of_Corrosion_Path_of_Darkness', cn='幽冥之径•侵蚀隧洞', cht='幽冥之徑•侵蝕隧洞', en='Path of Darkness', jp='侵蝕トンネル・幽冥の路', es='Senda de la oscuridad', + plane_id=2022301, +) +Cavern_of_Corrosion_Path_of_Dreamdive = DungeonList( + id=44, + name='Cavern_of_Corrosion_Path_of_Dreamdive', + cn='梦潜之径•侵蚀隧洞', + cht='夢潛之徑•侵蝕隧洞', + en='Path of Dreamdive', + jp='侵蝕トンネル・夢潜の路', + es='Senda de los sueños', + plane_id=2031101, ) Echo_of_War_Destruction_Beginning = DungeonList( - id=33, + id=45, name='Echo_of_War_Destruction_Beginning', cn='毁灭的开端•历战余响', cht='毀滅的開端•歷戰餘響', en="Destruction's Beginning", jp='歴戦余韻・壊滅の始まり', es='El principio de la Destrucción', + plane_id=2000301, ) Echo_of_War_End_of_the_Eternal_Freeze = DungeonList( - id=34, + id=46, name='Echo_of_War_End_of_the_Eternal_Freeze', cn='寒潮的落幕•历战余响', cht='寒潮的落幕•歷戰餘響', en='End of the Eternal Freeze', jp='歴戦余韻・寒波の幕切れ', es='El fin del Hielo Eterno', + plane_id=2013401, ) Echo_of_War_Divine_Seed = DungeonList( - id=35, + id=47, name='Echo_of_War_Divine_Seed', cn='不死的神实•历战余响', cht='不死的神實•歷戰餘響', en='Divine Seed', jp='歴戦余韻・不死の神実', es='Semilla divina', + plane_id=2023201, ) Echo_of_War_Borehole_Planet_Old_Crater = DungeonList( - id=36, + id=48, name='Echo_of_War_Borehole_Planet_Old_Crater', cn='蛀星的旧靥•历战余响', cht='蛀星的舊靨•歷戰餘響', en="Borehole Planet's Old Crater", jp='歴戦余韻・星を蝕む往日の面影', es='Cráter del planeta devorado', + plane_id=2000401, ) Simulated_Universe_World_1 = DungeonList( - id=37, + id=49, name='Simulated_Universe_World_1', cn='第一世界•模拟宇宙', cht='第一世界•模擬宇宙', en='Simulated Universe: World 1', jp='第一世界・模擬宇宙', es='Mundo 1', + plane_id=100000104, ) Simulated_Universe_World_3 = DungeonList( - id=38, + id=50, name='Simulated_Universe_World_3', cn='第三世界•模拟宇宙', cht='第三世界•模擬宇宙', en='Simulated Universe: World 3', jp='第三世界・模擬宇宙', es='Mundo 3', + plane_id=100000104, ) Simulated_Universe_World_4 = DungeonList( - id=39, + id=51, name='Simulated_Universe_World_4', cn='第四世界•模拟宇宙', cht='第四世界•模擬宇宙', en='Simulated Universe: World 4', jp='第四世界・模擬宇宙', es='Mundo 4', + plane_id=100000104, ) Simulated_Universe_World_5 = DungeonList( - id=40, + id=52, name='Simulated_Universe_World_5', cn='第五世界•模拟宇宙', cht='第五世界•模擬宇宙', en='Simulated Universe: World 5', jp='第五世界・模擬宇宙', es='Mundo 5', + plane_id=100000104, ) Simulated_Universe_World_6 = DungeonList( - id=41, + id=53, name='Simulated_Universe_World_6', cn='第六世界•模拟宇宙', cht='第六世界•模擬宇宙', en='Simulated Universe: World 6', jp='第六世界・模擬宇宙', es='Mundo 6', + plane_id=100000104, ) Simulated_Universe_World_7 = DungeonList( - id=42, + id=54, name='Simulated_Universe_World_7', cn='第七世界•模拟宇宙', cht='第七世界•模擬宇宙', en='Simulated Universe: World 7', jp='第七世界・模擬宇宙', es='Mundo 7', + plane_id=100000104, ) Simulated_Universe_World_8 = DungeonList( - id=43, + id=55, name='Simulated_Universe_World_8', cn='第八世界•模拟宇宙', cht='第八世界•模擬宇宙', en='Simulated Universe: World 8', jp='第八世界・模擬宇宙', es='Mundo 8', + plane_id=100000104, ) Simulated_Universe_The_Swarm_Disaster = DungeonList( - id=44, + id=56, name='Simulated_Universe_The_Swarm_Disaster', cn='寰宇蝗灾', cht='寰宇蝗災', en='The Swarm Disaster', jp='宇宙の蝗害', es='La Plaga', + plane_id=-1, ) Simulated_Universe_Gold_and_Gears = DungeonList( - id=45, + id=57, name='Simulated_Universe_Gold_and_Gears', cn='黄金与机械', cht='黃金與機械', en='Gold and Gears', jp='黄金と機械', es='Oro y maquinaria', + plane_id=-1, ) Memory_of_Chaos = DungeonList( - id=46, + id=58, name='Memory_of_Chaos', cn='混沌回忆', cht='混沌回憶', en='Memory of Chaos', jp='混沌の記憶', es='Evocación caótica', + plane_id=-1, ) The_Voyage_of_Navis_Astriger = DungeonList( - id=47, + id=59, name='The_Voyage_of_Navis_Astriger', cn='天艟求仙迷航录', cht='天艟求仙迷航錄', en='The Voyage of Navis Astriger', jp='天艟求仙放浪記', es='El viaje de las naves astriger', + plane_id=-1, ) The_Last_Vestiges_of_Towering_Citadel = DungeonList( - id=48, + id=60, name='The_Last_Vestiges_of_Towering_Citadel', cn='永屹之城遗秘', cht='永屹之城遺秘', en='The Last Vestiges of Towering Citadel', jp='永屹の城の秘密', es='Herencia de la Ciudadela Imponente', + plane_id=-1, ) diff --git a/tasks/dungeon/keywords/dungeon_detailed.py b/tasks/dungeon/keywords/dungeon_detailed.py index 6c752846d..89a905750 100644 --- a/tasks/dungeon/keywords/dungeon_detailed.py +++ b/tasks/dungeon/keywords/dungeon_detailed.py @@ -114,11 +114,11 @@ Stagnant_Shadow_Scorch = DungeonDetailed( Stagnant_Shadow_Celestial = DungeonDetailed( id=13, name='Stagnant_Shadow_Celestial', - cn='角色晋阶材料:风(刃 / 藿藿)', - cht='角色晉階材料:風(刃 / 藿藿)', - en='Ascension: Wind (Blade / Huohuo)', - jp='キャラクター昇格素材:風(刃 / フォフォ)', - es='Ascension: Viento (Blade / Huohuo)', + cn='角色晋阶材料:风(刃 / 藿藿 / 黑天鹅)', + cht='角色晉階材料:風(刃 / 藿藿 / 黑天鵝)', + en='Ascension: Wind (Blade / Huohuo / Black Swan)', + jp='キャラクター昇格素材:風(刃 / フォフォ / ブラックスワン)', + es='Ascension: Viento (Blade / Huohuo / Cisne Negro)', ) Stagnant_Shadow_Perdition = DungeonDetailed( id=14, @@ -129,3 +129,21 @@ Stagnant_Shadow_Perdition = DungeonDetailed( jp='キャラクター昇格素材:物理(寒鴉 / アルジェンティ)', es='Ascension: Físico (Hanya / Argenti)', ) +Stagnant_Shadow_Nectar = DungeonDetailed( + id=15, + name='Stagnant_Shadow_Nectar', + cn='角色晋阶材料:冰(米沙)', + cht='角色晉階材料:冰(米沙)', + en='Ascension: Ice (Misha)', + jp='キャラクター昇格素材:氷(ミーシャ)', + es='Ascension: Hielo (Misha)', +) +Stagnant_Shadow_Roast = DungeonDetailed( + id=16, + name='Stagnant_Shadow_Roast', + cn='角色晋阶材料:量子(花火)', + cht='角色晉階材料:量子(花火)', + en='Ascension: Quantum (Sparkle)', + jp='キャラクター昇格素材:量子(花火)', + es='Ascension: Cuántico (Sparkle)', +) diff --git a/tasks/dungeon/keywords/dungeon_entrance.py b/tasks/dungeon/keywords/dungeon_entrance.py index 4a3905cca..45165e7fb 100644 --- a/tasks/dungeon/keywords/dungeon_entrance.py +++ b/tasks/dungeon/keywords/dungeon_entrance.py @@ -3,8 +3,17 @@ from .classes import DungeonEntrance # This file was auto-generated, do not modify it manually. To generate: # ``` python -m dev_tools.keyword_extract ``` -Teleport = DungeonEntrance( +Enter = DungeonEntrance( id=1, + name='Enter', + cn='进入', + cht='進入', + en='Enter', + jp='入る', + es='Entrar', +) +Teleport = DungeonEntrance( + id=2, name='Teleport', cn='传送', cht='傳送', @@ -13,7 +22,7 @@ Teleport = DungeonEntrance( es='Ir', ) Navigate = DungeonEntrance( - id=2, + id=3, name='Navigate', cn='追踪', cht='追蹤', diff --git a/tasks/dungeon/state.py b/tasks/dungeon/state.py index 6cd691d3b..3f1865690 100644 --- a/tasks/dungeon/state.py +++ b/tasks/dungeon/state.py @@ -4,7 +4,7 @@ from module.base.base import ModuleBase from module.base.timer import Timer from module.base.utils import crop from module.config.stored.classes import now -from module.config.utils import DEFAULT_TIME +from module.config.utils import DEFAULT_TIME, get_server_next_monday_update, get_server_next_update from module.logger import logger from module.ocr.ocr import DigitCounter from tasks.base.ui import UI @@ -139,12 +139,37 @@ class DungeonState(UI): limit = 30 else: limit = 60 + + # Double event is not yet finished, do it today as possible + diff = get_server_next_update('04:00') - now() + if self.config.stored.DungeonDouble.relic > 0: + if diff < timedelta(hours=4): + # 4h recover 40 stamina, run double relic at today + logger.info(f'Just less than 4h til the next day, ' + f'double relic event is not yet finished, wait until 40') + limit = 40 + if self.config.stored.DungeonDouble.calyx > 0: + if diff < timedelta(hours=3): + logger.info(f'Just less than 3h til the next day, ' + f'double calyx event is not yet finished, wait until 10') + limit = 10 + elif diff < timedelta(hours=6): + logger.info(f'Just less than 6h til the next day, ' + f'double calyx event is not yet finished, wait until 30') + limit = 30 + # Recover 1 trailbaze power each 6 minutes current = self.config.stored.TrailblazePower.value cover = max(limit - current, 0) * 6 future = now() + timedelta(minutes=cover) logger.info(f'Currently has {current} need {cover} minutes to reach {limit}') + # Save stamina for the next week + next_monday = get_server_next_monday_update('04:00') + if next_monday - future < timedelta(hours=4): + logger.info(f'Approaching next monday, delay to {next_monday} instead') + future = next_monday + tasks = ['Dungeon', 'Weekly'] with self.config.multi_set(): for task in tasks: diff --git a/tasks/dungeon/ui.py b/tasks/dungeon/ui.py index f6648dcd8..8bf8bd27c 100644 --- a/tasks/dungeon/ui.py +++ b/tasks/dungeon/ui.py @@ -1,5 +1,6 @@ import re +import cv2 import numpy as np from module.base.base import ModuleBase @@ -9,7 +10,7 @@ from module.base.utils import get_color from module.exception import ScriptError from module.logger import logger from module.ocr.ocr import Ocr, OcrResultButton -from module.ocr.utils import split_and_pair_button_attr +from module.ocr.utils import split_and_pair_button_attr, split_and_pair_buttons from module.ui.draggable_list import DraggableList from module.ui.switch import Switch from tasks.base.page import page_guide @@ -27,6 +28,8 @@ from tasks.dungeon.keywords import ( ) from tasks.dungeon.keywords.classes import DungeonEntrance from tasks.dungeon.state import DungeonState +from tasks.map.interact.aim import inrange +from tasks.map.keywords import KEYWORDS_MAP_WORLD, MapPlane class DungeonTabSwitch(Switch): @@ -76,7 +79,11 @@ class OcrDungeonNav(Ocr): class OcrDungeonList(Ocr): def after_process(self, result): + # 乙太之蕾•雅利洛-Ⅵ + result = re.sub(r'-[VⅤ][IⅠ]', '-Ⅵ', result) + result = super().after_process(result) + if self.lang == 'cn': result = result.replace('翼', '巽') # 巽风之形 result = result.replace('皖A0', '50').replace('皖', '') @@ -85,15 +92,36 @@ class OcrDungeonList(Ocr): result = re.sub('^灼之形', '燔灼之形', result) # 蛀星的旧·历战余响 result = re.sub(r'蛀星的旧.*?历战', '蛀星的旧靥•历战', result) + + # 9支援仓段 + for word in 'Q9α': + result = result.removeprefix(word) return result +class OcrDungeonListCalyxCrimson(OcrDungeonList): + def _match_result(self, *args, **kwargs): + """ + Convert MapPlane object to their corresponding DungeonList object + """ + plane = super()._match_result(*args, **kwargs) + if plane is not None: + for dungeon in DungeonList.instances.values(): + if dungeon.is_Calyx_Crimson and dungeon.plane == plane: + return dungeon + return plane + + class OcrDungeonListLimitEntrance(OcrDungeonList): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.button = ClickButton((*self.button.area[:3], self.button.area[3] - 70)) +class OcrDungeonListCalyxCrimsonLimitEntrance(OcrDungeonListCalyxCrimson, OcrDungeonListLimitEntrance): + pass + + class DraggableDungeonNav(DraggableList): # 0.5 is the magic number to reach bottom in 1 swipe # but relax we still have retires when magic doesn't work @@ -104,25 +132,77 @@ class DraggableDungeonList(DraggableList): teleports: list[OcrResultButton] = [] navigates: list[OcrResultButton] = [] - def load_rows(self, main: ModuleBase): + # use_plane: True to use map planes to predict dungeons only. + # Can only be True in Calyx Crimson + use_plane = False + # limit_entrance: True to ensure the teleport button is insight + limit_entrance = False + + def load_rows(self, main: ModuleBase, allow_early_access=False): + """ + Args: + main: + allow_early_access: True to allow dungeons that are in temporarily early access during events + """ + relative_area = (0, 0, 1280, 120) + if self.use_plane: + self.keyword_class = [MapPlane, DungeonEntrance] + if self.limit_entrance: + self.ocr_class = OcrDungeonListCalyxCrimsonLimitEntrance + else: + self.ocr_class = OcrDungeonListCalyxCrimson + else: + self.keyword_class = [DungeonList, DungeonEntrance] + if self.limit_entrance: + self.ocr_class = OcrDungeonListLimitEntrance + else: + self.ocr_class = OcrDungeonList super().load_rows(main=main) + + # Check early access dungeons + buttons = DUNGEON_LIST.cur_buttons.copy() + for name, button in split_and_pair_buttons( + DUNGEON_LIST.cur_buttons, + split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Enter, + relative_area=relative_area + ): + logger.warning(f'Early access dungeon: {name}') + buttons.remove(name) + buttons.remove(button) + + # Remove early access dungeons + if not allow_early_access: + DUNGEON_LIST.cur_buttons = buttons + # From super.load_rows(), re-calculate indexes + indexes = [self.keyword2index(row.matched_keyword) + for row in self.cur_buttons] + indexes = [index for index in indexes if index] + + if not indexes: + logger.warning(f'No valid rows loaded into {self}') + return + + self.cur_min = min(indexes) + self.cur_max = max(indexes) + logger.attr(self.name, f'{self.cur_min} - {self.cur_max}') + # Replace dungeon.button with teleport self.teleports = list(split_and_pair_button_attr( DUNGEON_LIST.cur_buttons, - split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Teleport, - relative_area=(0, 0, 1280, 120) + split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Teleport and x != KEYWORDS_DUNGEON_ENTRANCE.Enter, + relative_area=relative_area )) self.navigates = list(split_and_pair_button_attr( DUNGEON_LIST.cur_buttons, split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Navigate, - relative_area=(0, 0, 1280, 120) + relative_area=relative_area )) DUNGEON_NAV_LIST = DraggableDungeonNav( 'DungeonNavList', keyword_class=DungeonNav, ocr_class=OcrDungeonNav, search_button=OCR_DUNGEON_NAV) DUNGEON_LIST = DraggableDungeonList( - 'DungeonList', keyword_class=[DungeonList, DungeonEntrance], + 'DungeonList', keyword_class=[DungeonList, DungeonEntrance, MapPlane], ocr_class=OcrDungeonList, search_button=OCR_DUNGEON_LIST) @@ -214,6 +294,8 @@ class DungeonUI(DungeonState): in: page_guide, Survival_Index """ timeout = Timer(2, count=4).start() + TREASURES_LIGHTWARD_LOADED.set_search_offset((5, 5)) + TREASURES_LIGHTWARD_LOCKED.set_search_offset((5, 5)) while 1: if skip_first_screenshot: skip_first_screenshot = False @@ -224,8 +306,33 @@ class DungeonUI(DungeonState): logger.warning('Wait treasures lightward loaded timeout') return False if self.appear(TREASURES_LIGHTWARD_LOADED): - logger.info('Treasures lightward loaded') + logger.info('Treasures lightward loaded (event unlocked)') return True + if self.appear(TREASURES_LIGHTWARD_LOCKED): + logger.info('Treasures lightward loaded (event locked)') + return True + + def _dungeon_wait_until_dungeon_list_loaded(self, skip_first_screenshot=True): + timeout = Timer(1, count=3).start() + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if timeout.reached(): + logger.warning('Wait until dungeon list loaded timeout') + return False + + # Check if having any content + # List background: 254, guild border: 225 + r, g, b = cv2.split(self.image_crop(LIST_LOADED_CHECK)) + minimum = cv2.min(cv2.min(r, g), b) + minimum = inrange(minimum, lower=0, upper=180) + if minimum.size > 100: + logger.info('Dungeon list loaded') + break def _dungeon_wait_until_echo_or_war_stabled(self, skip_first_screenshot=True): """ @@ -261,17 +368,17 @@ class DungeonUI(DungeonState): logger.info('No Echo_of_War in list skip waiting') return False - def _dungeon_nav_goto(self, dungeon: DungeonList, skip_first_screenshot=True): + def _dungeon_nav_goto(self, nav: DungeonNav, skip_first_screenshot=True): """ Equivalent to `DUNGEON_NAV_LIST.select_row(dungeon.dungeon_nav, main=self)` but with tricks to be faster Args: - dungeon: + nav: skip_first_screenshot: """ logger.hr('Dungeon nav goto', level=2) - logger.info(f'Dungeon nav goto {dungeon.dungeon_nav}') + logger.info(f'Dungeon nav goto {nav}') # Wait rows while 1: @@ -312,11 +419,11 @@ class DungeonUI(DungeonState): else: # To start from any list states. logger.info('DUNGEON_NAV_LIST not at top') - DUNGEON_NAV_LIST.select_row(dungeon.dungeon_nav, main=self) + DUNGEON_NAV_LIST.select_row(nav, main=self) return True # Check the first page - if dungeon.dungeon_nav in [ + if nav in [ KEYWORDS_DUNGEON_NAV.Simulated_Universe, KEYWORDS_DUNGEON_NAV.Calyx_Golden, KEYWORDS_DUNGEON_NAV.Calyx_Crimson, @@ -325,9 +432,9 @@ class DungeonUI(DungeonState): KEYWORDS_DUNGEON_NAV.Forgotten_Hall, KEYWORDS_DUNGEON_NAV.Pure_Fiction, ]: - button = DUNGEON_NAV_LIST.keyword2button(dungeon.dungeon_nav) + button = DUNGEON_NAV_LIST.keyword2button(nav) if button: - DUNGEON_NAV_LIST.select_row(dungeon.dungeon_nav, main=self, insight=False) + DUNGEON_NAV_LIST.select_row(nav, main=self, insight=False) return True # Check the second page @@ -335,9 +442,88 @@ class DungeonUI(DungeonState): DUNGEON_NAV_LIST.drag_page('down', main=self) # No skip_first_screenshot since drag_page is just called if self._dungeon_wait_until_echo_or_war_stabled(skip_first_screenshot=False): - DUNGEON_NAV_LIST.select_row(dungeon.dungeon_nav, main=self, insight=False) + DUNGEON_NAV_LIST.select_row(nav, main=self, insight=False) return True + def _dungeon_world_set(self, dungeon: DungeonList, skip_first_screenshot=True): + """ + Switch worlds in Calyx_Golden + + Returns: + bool: True if success to set + """ + logger.hr('Dungeon world set', level=2) + if not dungeon.is_Calyx_Golden: + logger.warning(f'Dungeon {dungeon} is not Calyx Golden, no need to set world') + return False + if dungeon.world is None: + logger.error(f'Dungeon {dungeon} does not belongs to any world') + return False + dic_world_button = { + KEYWORDS_MAP_WORLD.Jarilo_VI: CALYX_WORLD_1, + KEYWORDS_MAP_WORLD.The_Xianzhou_Luofu: CALYX_WORLD_2, + KEYWORDS_MAP_WORLD.Penacony: CALYX_WORLD_3, + } + button = dic_world_button.get(dungeon.world) + if button is None: + logger.error(f'Dungeon {dungeon} with world {dungeon.world} has no corresponding world button') + return False + + logger.info(f'Dungeon world set {dungeon.world}') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.image_color_count(button, color=(18, 18, 18), threshold=180, count=50): + logger.info(f'Dungeon world at {dungeon.world}') + return True + # Click + if self.ui_page_appear(page_guide, interval=2): + self.device.click(button) + continue + + def _dungeon_world_set_wrapper(self, dungeon: DungeonList, skip_first_screenshot=True): + """ + Switch worlds in Calyx_Golden with error handling + If world tab is not unlocked, fallback to Jarilo dungeons + """ + # Wait world tab + button = CALYX_WORLD_1 + tab = False + timeout = Timer(0.6, count=3).start() + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + # End + if timeout.reached(): + break + # Selected tab + if self.image_color_count(button, color=(18, 18, 18), threshold=180, count=50): + tab = True + break + # Unselected tab + if self.image_color_count(button, color=(134, 134, 134), threshold=180, count=50): + tab = True + break + + logger.attr('WorldTab', tab) + if not tab: + logger.warning('World tab is not unlocked, fallback to Jarilo dungeons') + if dungeon.is_Calyx_Golden_Memories: + dungeon = KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures_Jarilo_VI + if dungeon.is_Calyx_Golden_Aether: + dungeon = KEYWORDS_DUNGEON_LIST.Calyx_Golden_Aether_Jarilo_VI + if dungeon.is_Calyx_Golden_Treasures: + dungeon = KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures_Jarilo_VI + + self._dungeon_world_set(dungeon, skip_first_screenshot=skip_first_screenshot) + return dungeon + def _dungeon_insight(self, dungeon: DungeonList): """ Pages: @@ -345,6 +531,7 @@ class DungeonUI(DungeonState): out: page_guide, Survival_Index, nav including dungeon, dungeon insight """ logger.hr('Dungeon insight', level=2) + DUNGEON_LIST.use_plane = bool(dungeon.is_Calyx_Crimson) # Insight dungeon DUNGEON_LIST.insight_row(dungeon, main=self) # Check if dungeon unlocked @@ -363,10 +550,10 @@ class DungeonUI(DungeonState): DUNGEON_LIST.drag_vector = (-0.4, -0.2) # Keyword loaded is reversed else: DUNGEON_LIST.drag_vector = (0.2, 0.4) - DUNGEON_LIST.ocr_class = OcrDungeonListLimitEntrance + DUNGEON_LIST.limit_entrance = True DUNGEON_LIST.insight_row(dungeon, main=self) DUNGEON_LIST.drag_vector = DraggableList.drag_vector - DUNGEON_LIST.ocr_class = OcrDungeonList + DUNGEON_LIST.limit_entrance = False DUNGEON_LIST.load_rows(main=self) # Check if dungeon unlocked for entrance in DUNGEON_LIST.navigates: @@ -383,6 +570,7 @@ class DungeonUI(DungeonState): out: COMBAT_PREPARE, FORGOTTEN_HALL_CHECK """ logger.hr('Dungeon enter', level=2) + DUNGEON_LIST.use_plane = bool(dungeon.is_Calyx_Crimson) skip_first_load = True while 1: if skip_first_screenshot: @@ -478,7 +666,7 @@ class DungeonUI(DungeonState): if self.appear(SURVIVAL_INDEX_LOADED): logger.info('Already at nav Simulated_Universe') else: - self._dungeon_nav_goto(KEYWORDS_DUNGEON_LIST.Simulated_Universe_World_1) + self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Simulated_Universe) def dungeon_goto(self, dungeon: DungeonList): """ @@ -500,12 +688,20 @@ class DungeonUI(DungeonState): # Reset search button DUNGEON_LIST.search_button = OCR_DUNGEON_LIST - if dungeon.is_Calyx_Golden \ - or dungeon.is_Calyx_Crimson \ + if dungeon.is_Calyx_Crimson \ or dungeon.is_Stagnant_Shadow \ or dungeon.is_Cavern_of_Corrosion \ or dungeon.is_Echo_of_War: - self._dungeon_nav_goto(dungeon) + self._dungeon_nav_goto(dungeon.dungeon_nav) + self._dungeon_wait_until_dungeon_list_loaded() + self._dungeon_insight(dungeon) + self._dungeon_enter(dungeon) + return True + if dungeon.is_Calyx_Golden: + self._dungeon_nav_goto(dungeon.dungeon_nav) + self._dungeon_wait_until_dungeon_list_loaded() + dungeon = self._dungeon_world_set_wrapper(dungeon) + self._dungeon_wait_until_dungeon_list_loaded() self._dungeon_insight(dungeon) self._dungeon_enter(dungeon) return True diff --git a/tasks/dungeon/weekly.py b/tasks/dungeon/weekly.py index d0f1962bf..846104f47 100644 --- a/tasks/dungeon/weekly.py +++ b/tasks/dungeon/weekly.py @@ -3,7 +3,7 @@ from module.ocr.ocr import DigitCounter from tasks.daily.keywords import KEYWORDS_DAILY_QUEST from tasks.dungeon.assets.assets_dungeon_ui import OCR_DUNGEON_LIST, OCR_WEEKLY_LIMIT from tasks.dungeon.dungeon import Dungeon -from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_TAB +from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_NAV, KEYWORDS_DUNGEON_TAB from tasks.dungeon.ui import DUNGEON_LIST @@ -15,8 +15,7 @@ class WeeklyDungeon(Dungeon): skip_ui_switch: bool = False): if team is None: team = self.config.Weekly_Team - # No support - support_character = '' + skip_ui_switch = True return super()._dungeon_run( dungeon=dungeon, team=team, wave_limit=wave_limit, @@ -53,7 +52,8 @@ class WeeklyDungeon(Dungeon): self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) # Equivalent to self.dungeon_goto(dungeon), but check limit remains DUNGEON_LIST.search_button = OCR_DUNGEON_LIST - self._dungeon_nav_goto(dungeon) + self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Echo_of_War) + self._dungeon_wait_until_dungeon_list_loaded() # Check limit remain = self.get_weekly_remain() diff --git a/tasks/forgotten_hall/assets/assets_forgotten_hall_nav.py b/tasks/forgotten_hall/assets/assets_forgotten_hall_nav.py new file mode 100644 index 000000000..7b9b82fa4 --- /dev/null +++ b/tasks/forgotten_hall/assets/assets_forgotten_hall_nav.py @@ -0,0 +1,95 @@ +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 ``` + +LAST_VASTIGES_CHECK = ButtonWrapper( + name='LAST_VASTIGES_CHECK', + share=[ + Button( + file='./assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.png', + area=(25, 190, 96, 262), + search=(11, 73, 111, 461), + color=(94, 126, 162), + button=(25, 190, 96, 262), + ), + Button( + file='./assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.2.png', + area=(46, 274, 98, 348), + search=(11, 73, 111, 461), + color=(38, 53, 71), + button=(46, 274, 98, 348), + ), + Button( + file='./assets/share/forgotten_hall/nav/LAST_VASTIGES_CHECK.3.png', + area=(73, 205, 84, 239), + search=(11, 73, 111, 461), + color=(51, 64, 79), + button=(73, 205, 84, 239), + ), + ], +) +LAST_VASTIGES_CLICK = ButtonWrapper( + name='LAST_VASTIGES_CLICK', + share=[ + Button( + file='./assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.png', + area=(32, 196, 90, 254), + search=(11, 73, 111, 461), + color=(49, 64, 87), + button=(32, 196, 90, 254), + ), + Button( + file='./assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.2.png', + area=(51, 281, 90, 341), + search=(11, 73, 111, 461), + color=(22, 29, 39), + button=(51, 281, 90, 341), + ), + Button( + file='./assets/share/forgotten_hall/nav/LAST_VASTIGES_CLICK.3.png', + area=(73, 211, 79, 236), + search=(11, 73, 111, 461), + color=(34, 39, 44), + button=(73, 211, 79, 236), + ), + ], +) +MEMORY_OF_CHAOS_CHECK = ButtonWrapper( + name='MEMORY_OF_CHAOS_CHECK', + share=[ + Button( + file='./assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.png', + area=(24, 90, 96, 162), + search=(4, 70, 116, 182), + color=(140, 116, 159), + button=(24, 90, 96, 162), + ), + Button( + file='./assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CHECK.2.png', + area=(46, 94, 98, 168), + search=(26, 74, 118, 188), + color=(67, 57, 79), + button=(46, 94, 98, 168), + ), + ], +) +MEMORY_OF_CHAOS_CLICK = ButtonWrapper( + name='MEMORY_OF_CHAOS_CLICK', + share=[ + Button( + file='./assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.png', + area=(51, 96, 90, 154), + search=(31, 76, 110, 174), + color=(82, 67, 99), + button=(51, 96, 90, 154), + ), + Button( + file='./assets/share/forgotten_hall/nav/MEMORY_OF_CHAOS_CLICK.2.png', + area=(51, 102, 90, 160), + search=(31, 82, 110, 180), + color=(47, 43, 56), + button=(51, 102, 90, 160), + ), + ], +) diff --git a/tasks/forgotten_hall/assets/assets_forgotten_hall_ui.py b/tasks/forgotten_hall/assets/assets_forgotten_hall_ui.py index 96a9343f4..778930ee2 100644 --- a/tasks/forgotten_hall/assets/assets_forgotten_hall_ui.py +++ b/tasks/forgotten_hall/assets/assets_forgotten_hall_ui.py @@ -43,64 +43,6 @@ ENTRANCE_CHECKED = ButtonWrapper( button=(44, 655, 60, 673), ), ) -LAST_VASTIGES_CHECK = ButtonWrapper( - name='LAST_VASTIGES_CHECK', - share=[ - Button( - file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.png', - area=(25, 190, 96, 262), - search=(11, 73, 111, 461), - color=(94, 126, 162), - button=(25, 190, 96, 262), - ), - Button( - file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.2.png', - area=(46, 274, 98, 348), - search=(11, 73, 111, 461), - color=(38, 53, 71), - button=(46, 274, 98, 348), - ), - ], -) -LAST_VASTIGES_CLICK = ButtonWrapper( - name='LAST_VASTIGES_CLICK', - share=[ - Button( - file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.png', - area=(32, 196, 90, 254), - search=(11, 73, 111, 461), - color=(49, 64, 87), - button=(32, 196, 90, 254), - ), - Button( - file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.2.png', - area=(51, 281, 90, 341), - search=(11, 73, 111, 461), - color=(22, 29, 39), - button=(51, 281, 90, 341), - ), - ], -) -MEMORY_OF_CHAOS_CHECK = ButtonWrapper( - name='MEMORY_OF_CHAOS_CHECK', - share=Button( - file='./assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CHECK.png', - area=(24, 90, 96, 162), - search=(4, 70, 116, 182), - color=(140, 116, 159), - button=(24, 90, 96, 162), - ), -) -MEMORY_OF_CHAOS_CLICK = ButtonWrapper( - name='MEMORY_OF_CHAOS_CLICK', - share=Button( - file='./assets/share/forgotten_hall/ui/MEMORY_OF_CHAOS_CLICK.png', - area=(32, 96, 90, 154), - search=(12, 76, 110, 174), - color=(74, 60, 96), - button=(32, 96, 90, 154), - ), -) OCR_STAGE = ButtonWrapper( name='OCR_STAGE', share=Button( @@ -155,9 +97,9 @@ TELEPORT = ButtonWrapper( name='TELEPORT', share=Button( file='./assets/share/forgotten_hall/ui/TELEPORT.png', - area=(1019, 451, 1037, 470), + area=(1018, 355, 1038, 375), search=(993, 176, 1088, 658), - color=(166, 165, 166), - button=(1019, 451, 1037, 470), + color=(80, 83, 85), + button=(1018, 355, 1038, 375), ), ) diff --git a/tasks/forgotten_hall/ui.py b/tasks/forgotten_hall/ui.py index ee1382938..a07c08753 100644 --- a/tasks/forgotten_hall/ui.py +++ b/tasks/forgotten_hall/ui.py @@ -10,8 +10,9 @@ from module.ocr.keyword import Keyword from module.ocr.ocr import Ocr, OcrResultButton from module.ui.draggable_list import DraggableList from tasks.base.assets.assets_base_page import FORGOTTEN_HALL_CHECK, MAP_EXIT -from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_DUNGEON_TAB +from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_DUNGEON_NAV, KEYWORDS_DUNGEON_TAB from tasks.dungeon.ui import DungeonUI +from tasks.forgotten_hall.assets.assets_forgotten_hall_nav import * from tasks.forgotten_hall.assets.assets_forgotten_hall_ui import * from tasks.forgotten_hall.keywords import ForgottenHallStage, KEYWORDS_FORGOTTEN_HALL_STAGE from tasks.forgotten_hall.team import ForgottenHallTeam @@ -186,7 +187,7 @@ class ForgottenHallUI(DungeonUI, ForgottenHallTeam): logger.info('Already in forgotten hall') else: self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Treasures_Lightward) - self._dungeon_nav_goto(dungeon) + self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Forgotten_Hall) self.stage_choose(dungeon) logger.info(f'Stage list select: {stage_keyword}') diff --git a/tasks/freebies/assets/assets_freebies_support_reward.py b/tasks/freebies/assets/assets_freebies_support_reward.py index a8e03e558..56d950635 100644 --- a/tasks/freebies/assets/assets_freebies_support_reward.py +++ b/tasks/freebies/assets/assets_freebies_support_reward.py @@ -7,30 +7,20 @@ CAN_GET_REWARD = ButtonWrapper( name='CAN_GET_REWARD', share=Button( file='./assets/share/freebies/support_reward/CAN_GET_REWARD.png', - area=(1055, 266, 1106, 310), - search=(1035, 246, 1126, 330), - color=(229, 186, 123), - button=(1055, 266, 1106, 310), - ), -) -CLICKING_REWARD = ButtonWrapper( - name='CLICKING_REWARD', - share=Button( - file='./assets/share/freebies/support_reward/CLICKING_REWARD.png', - area=(1066, 268, 1105, 307), - search=(1046, 248, 1125, 327), - color=(197, 161, 111), - button=(1066, 268, 1105, 307), + area=(1066, 121, 1097, 144), + search=(1046, 101, 1117, 164), + color=(245, 225, 170), + button=(1066, 121, 1097, 144), ), ) IN_PROFILE = ButtonWrapper( name='IN_PROFILE', share=Button( file='./assets/share/freebies/support_reward/IN_PROFILE.png', - area=(643, 106, 673, 131), - search=(623, 86, 693, 151), - color=(74, 67, 58), - button=(643, 106, 673, 131), + area=(647, 128, 673, 146), + search=(627, 108, 693, 166), + color=(109, 97, 83), + button=(647, 128, 673, 146), ), ) MENU_TO_PROFILE = ButtonWrapper( diff --git a/tasks/item/consumable_usage.py b/tasks/item/consumable_usage.py index 07224982d..6df481dc5 100644 --- a/tasks/item/consumable_usage.py +++ b/tasks/item/consumable_usage.py @@ -8,7 +8,7 @@ from tasks.daily.assets.assets_daily_synthesize_consumable import \ from tasks.daily.synthesize import SynthesizeConsumablesUI from tasks.item.assets.assets_item_consumable_usage import * from tasks.item.assets.assets_item_ui import CONSUMABLE_CHECK -from tasks.item.keywords import KEYWORD_ITEM_TAB +from tasks.item.keywords import KEYWORDS_ITEM_TAB from tasks.item.ui import ItemUI @@ -28,7 +28,7 @@ class ConsumableUsageUI(ItemUI): """ logger.hr('Use consumable', level=2) self.ui_ensure(page_item) - self.item_goto(KEYWORD_ITEM_TAB.Consumables) + self.item_goto(KEYWORDS_ITEM_TAB.Consumables) if self._search_and_select_consumable(): self._click_use() self._confirm_use() @@ -50,7 +50,7 @@ class ConsumableUsageUI(ItemUI): # because in this scenario, scroll bar delay appears and the previous screenshot was # taken after clicking on the "item" to determine whether to enter the "item", which may be inaccurate # self._switch_tag_to_consumables(False) - self.item_goto(KEYWORD_ITEM_TAB.Consumables) + self.item_goto(KEYWORDS_ITEM_TAB.Consumables) # Determine if there is a scroll bar. If there is a scroll bar, # pull it down and check if the consumable to be used can be found diff --git a/tasks/item/keywords/__init__.py b/tasks/item/keywords/__init__.py index e37815a8c..079bcd293 100644 --- a/tasks/item/keywords/__init__.py +++ b/tasks/item/keywords/__init__.py @@ -1,2 +1,2 @@ -import tasks.item.keywords.tab as KEYWORD_ITEM_TAB +import tasks.item.keywords.tab as KEYWORDS_ITEM_TAB from tasks.item.keywords.classes import ItemTab diff --git a/tasks/item/relics.py b/tasks/item/relics.py index 7febb0751..d0b3d916b 100644 --- a/tasks/item/relics.py +++ b/tasks/item/relics.py @@ -2,7 +2,7 @@ from module.base.timer import Timer from module.logger import logger from tasks.base.assets.assets_base_page import CLOSE from tasks.item.assets.assets_item_relics import * -from tasks.item.keywords import KEYWORD_ITEM_TAB +from tasks.item.keywords import KEYWORDS_ITEM_TAB from tasks.item.ui import ItemUI @@ -48,7 +48,7 @@ class RelicsUI(ItemUI): out: page_item, GOTO_SALVAGE """ logger.hr('Salvage Relic', level=2) - self.item_goto(KEYWORD_ITEM_TAB.Relics, wait_until_stable=False) + self.item_goto(KEYWORDS_ITEM_TAB.Relics, wait_until_stable=False) while 1: # relic tab -> salvage if skip_first_screenshot: skip_first_screenshot = False diff --git a/tasks/item/ui.py b/tasks/item/ui.py index 78d9151cf..23ae5561a 100644 --- a/tasks/item/ui.py +++ b/tasks/item/ui.py @@ -4,48 +4,48 @@ from tasks.base.page import page_item from tasks.base.ui import UI from tasks.item.assets.assets_item_consumable_usage import SIMPLE_PROTECTIVE_GEAR from tasks.item.assets.assets_item_ui import * -from tasks.item.keywords import KEYWORD_ITEM_TAB +from tasks.item.keywords import KEYWORDS_ITEM_TAB SWITCH_ITEM_TAB = Switch('ItemTab', is_selector=True) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.UpgradeMaterials, + KEYWORDS_ITEM_TAB.UpgradeMaterials, check_button=UPGRADE_MATERIAL_CHECK, click_button=UPGRADE_MATERIAL_CLICK ) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.LightCone, + KEYWORDS_ITEM_TAB.LightCone, check_button=LIGHT_CONE_CHECK, click_button=LIGHT_CONE_CLICK ) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.Relics, + KEYWORDS_ITEM_TAB.Relics, check_button=RELICS_CHECK, click_button=RELICS_CLICK ) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.OtherMaterials, + KEYWORDS_ITEM_TAB.OtherMaterials, check_button=OTHER_MATERIALS_CHECK, click_button=OTHER_MATERIALS_CLICK ) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.Consumables, + KEYWORDS_ITEM_TAB.Consumables, check_button=CONSUMABLE_CHECK, click_button=CONSUMABLE_CLICK, ) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.Missions, + KEYWORDS_ITEM_TAB.Missions, check_button=MISSIONS_CHECK, click_button=MISSIONS_CLICK ) SWITCH_ITEM_TAB.add_state( - KEYWORD_ITEM_TAB.Valuables, + KEYWORDS_ITEM_TAB.Valuables, check_button=VALUABLES_CHECK, click_button=VALUABLES_CLICK ) class ItemUI(UI): - def item_goto(self, state: KEYWORD_ITEM_TAB, wait_until_stable=True): + def item_goto(self, state: KEYWORDS_ITEM_TAB, wait_until_stable=True): """ Args: state: @@ -55,8 +55,8 @@ class ItemUI(UI): Returns: self = ItemUI('alas') self.device.screenshot() - self.item_goto(KEYWORD_ITEM_TAB.Relics) - self.item_goto(KEYWORD_ITEM_TAB.Consumables) + self.item_goto(KEYWORDS_ITEM_TAB.Relics) + self.item_goto(KEYWORDS_ITEM_TAB.Consumables) """ logger.hr('Item tab goto', level=2) self.ui_ensure(page_item) diff --git a/tasks/map/assets/assets_map_control.py b/tasks/map/assets/assets_map_control.py index 142d1b8d6..6aaa78af9 100644 --- a/tasks/map/assets/assets_map_control.py +++ b/tasks/map/assets/assets_map_control.py @@ -7,20 +7,20 @@ A_BUTTON = ButtonWrapper( name='A_BUTTON', share=Button( file='./assets/share/map/control/A_BUTTON.png', - area=(998, 508, 1078, 588), - search=(978, 488, 1098, 608), - color=(85, 86, 89), - button=(998, 508, 1078, 588), + area=(1023, 521, 1083, 581), + search=(1003, 501, 1103, 601), + color=(108, 109, 110), + button=(1023, 521, 1083, 581), ), ) E_BUTTON = ButtonWrapper( name='E_BUTTON', share=Button( file='./assets/share/map/control/E_BUTTON.png', - area=(875, 583, 944, 650), - search=(855, 563, 964, 670), - color=(67, 68, 71), - button=(875, 583, 944, 650), + area=(897, 592, 947, 642), + search=(877, 572, 967, 662), + color=(75, 77, 82), + button=(897, 592, 947, 642), ), ) JOYSTICK = ButtonWrapper( @@ -47,59 +47,59 @@ RUN_BUTTON = ButtonWrapper( name='RUN_BUTTON', share=Button( file='./assets/share/map/control/RUN_BUTTON.png', - area=(1125, 582, 1191, 651), - search=(1105, 562, 1211, 671), - color=(73, 76, 83), - button=(1125, 582, 1191, 651), + area=(1147, 591, 1195, 639), + search=(1127, 571, 1215, 659), + color=(105, 110, 138), + button=(1147, 591, 1195, 639), ), ) TECHNIQUE_POINT_1 = ButtonWrapper( name='TECHNIQUE_POINT_1', share=Button( file='./assets/share/map/control/TECHNIQUE_POINT_1.png', - area=(854, 594, 867, 607), - search=(834, 574, 887, 627), + area=(881, 594, 894, 607), + search=(861, 574, 914, 627), color=(149, 141, 186), - button=(854, 594, 867, 607), + button=(881, 594, 894, 607), ), ) TECHNIQUE_POINT_2 = ButtonWrapper( name='TECHNIQUE_POINT_2', share=Button( file='./assets/share/map/control/TECHNIQUE_POINT_2.png', - area=(862, 578, 876, 592), - search=(842, 558, 896, 612), + area=(889, 578, 903, 592), + search=(869, 558, 923, 612), color=(139, 132, 174), - button=(862, 578, 876, 592), + button=(889, 578, 903, 592), ), ) TECHNIQUE_POINT_3 = ButtonWrapper( name='TECHNIQUE_POINT_3', share=Button( file='./assets/share/map/control/TECHNIQUE_POINT_3.png', - area=(875, 566, 889, 580), - search=(855, 546, 909, 600), + area=(902, 566, 916, 580), + search=(882, 546, 936, 600), color=(138, 130, 173), - button=(875, 566, 889, 580), + button=(902, 566, 916, 580), ), ) TECHNIQUE_POINT_4 = ButtonWrapper( name='TECHNIQUE_POINT_4', share=Button( file='./assets/share/map/control/TECHNIQUE_POINT_4.png', - area=(891, 559, 905, 573), - search=(871, 539, 925, 593), + area=(918, 559, 932, 573), + search=(898, 539, 952, 593), color=(138, 130, 173), - button=(891, 559, 905, 573), + button=(918, 559, 932, 573), ), ) TECHNIQUE_POINT_5 = ButtonWrapper( name='TECHNIQUE_POINT_5', share=Button( file='./assets/share/map/control/TECHNIQUE_POINT_5.png', - area=(908, 559, 921, 573), - search=(888, 539, 941, 593), + area=(935, 559, 948, 573), + search=(915, 539, 968, 593), color=(71, 72, 77), - button=(908, 559, 921, 573), + button=(935, 559, 948, 573), ), ) diff --git a/tasks/map/bigmap/plane.py b/tasks/map/bigmap/plane.py index 32c6eb812..afc6caf52 100644 --- a/tasks/map/bigmap/plane.py +++ b/tasks/map/bigmap/plane.py @@ -17,11 +17,11 @@ FLOOR_BUTTONS = [FLOOR_1, FLOOR_2, FLOOR_3] def world_entrance(plane: MapPlane) -> ButtonWrapper: - if plane.is_HertaSpaceStation: + if plane.world.is_Herta: return WORLD_HERTA - if plane.is_JariloVI: + if plane.world.is_Jarilo: return WORLD_JARILO - if plane.is_Luofu: + if plane.world.is_Luofu: return WORLD_LUOFU raise ScriptError(f'world_entrance() got unknown plane: {plane}') diff --git a/tasks/map/keywords/classes.py b/tasks/map/keywords/classes.py index 2ac377ced..a071b7cab 100644 --- a/tasks/map/keywords/classes.py +++ b/tasks/map/keywords/classes.py @@ -10,6 +10,11 @@ from module.ocr.keyword import Keyword class MapPlane(Keyword): instances: ClassVar = {} + # 0, 1, 2, 3 + world_id: int + # 1010201 + plane_id: int + # Map floors, 'F1' by default # Example: ['B1', 'F1', 'F2'] floors = ['F1'] @@ -18,33 +23,30 @@ class MapPlane(Keyword): # 'top' or 'bottom' page = 'top' + @classmethod + def find_plane_id(cls, plane_id): + """ + Args: + plane_id: + + Returns: + MapPlane: MapPlane object or None + """ + for instance in cls.instances.values(): + if instance.plane_id == plane_id: + return instance + return None + + def __hash__(self) -> int: + return super().__hash__() + @cached_property - def world(self) -> str: + def world(self) -> "MapWorld": """ 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 + MapWorld: MapWorld object or None """ - 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' + return MapWorld.find_world_id(self.world_id) @cached_property def has_multiple_floors(self): @@ -135,3 +137,41 @@ class MapPlane(Keyword): @dataclass(repr=False) class MapWorld(Keyword): instances: ClassVar = {} + + # 0, 1, 2, 3 + world_id: int + # Herta + short_name: str + + @classmethod + def find_world_id(cls, world_id): + """ + Args: + world_id: + + Returns: + MapWorld: MapWorld object or None + """ + for instance in cls.instances.values(): + if instance.world_id == world_id: + return instance + return None + + def __hash__(self) -> int: + return super().__hash__() + + @cached_property + def is_Herta(self): + return self.short_name == 'Herta' + + @cached_property + def is_Jarilo(self): + return self.short_name == 'Jarilo' + + @cached_property + def is_Luofu(self): + return self.short_name == 'Luofu' + + @cached_property + def is_Penacony(self): + return self.short_name == 'Penacony' diff --git a/tasks/map/keywords/plane.py b/tasks/map/keywords/plane.py index 160450a02..7e2fc76c7 100644 --- a/tasks/map/keywords/plane.py +++ b/tasks/map/keywords/plane.py @@ -11,6 +11,8 @@ Special_HertaOffice = MapPlane( en="Herta's Office", jp='ヘルタのオフィス', es='Oficina de Herta', + world_id=-1, + plane_id=1, ) Special_AptitudeShowcase = MapPlane( id=2, @@ -20,6 +22,8 @@ Special_AptitudeShowcase = MapPlane( en='Aptitude Showcase', jp='躍進する新星', es='Demostración de aptitudes', + world_id=-1, + plane_id=2, ) Rogue_DomainCombat = MapPlane( id=3, @@ -29,6 +33,8 @@ Rogue_DomainCombat = MapPlane( en='Domain — Combat', jp='エリア-戦闘', es='Batalla', + world_id=-2, + plane_id=1, ) Rogue_DomainOccurrence = MapPlane( id=4, @@ -38,6 +44,8 @@ Rogue_DomainOccurrence = MapPlane( en='Domain — Occurrence', jp='エリア-イベント', es='Evento', + world_id=-2, + plane_id=2, ) Rogue_DomainEncounter = MapPlane( id=5, @@ -47,6 +55,8 @@ Rogue_DomainEncounter = MapPlane( en='Domain — Encounter', jp='エリア-遭遇', es='Encuentro', + world_id=-2, + plane_id=3, ) Rogue_DomainRespite = MapPlane( id=6, @@ -56,6 +66,8 @@ Rogue_DomainRespite = MapPlane( en='Domain — Respite', jp='エリア-休憩', es='Reposo', + world_id=-2, + plane_id=4, ) Rogue_DomainElite = MapPlane( id=7, @@ -65,6 +77,8 @@ Rogue_DomainElite = MapPlane( en='Domain — Elite', jp='エリア-精鋭', es='Élite', + world_id=-2, + plane_id=5, ) Rogue_DomainBoss = MapPlane( id=8, @@ -74,6 +88,8 @@ Rogue_DomainBoss = MapPlane( en='Domain — Boss', jp='エリア-ボス', es='Jefe', + world_id=-2, + plane_id=6, ) Rogue_DomainTransaction = MapPlane( id=9, @@ -83,6 +99,8 @@ Rogue_DomainTransaction = MapPlane( en='Domain — Transaction', jp='エリア-取引', es='Transacción', + world_id=-2, + plane_id=7, ) Herta_ParlorCar = MapPlane( id=10, @@ -92,6 +110,8 @@ Herta_ParlorCar = MapPlane( en='Parlor Car', jp='列車のラウンジ', es='Vagón panorámico', + world_id=0, + plane_id=1000001, ) Herta_MasterControlZone = MapPlane( id=11, @@ -101,6 +121,8 @@ Herta_MasterControlZone = MapPlane( en='Master Control Zone', jp='主制御部分', es='Zona de mando principal', + world_id=0, + plane_id=1000101, ) Herta_BaseZone = MapPlane( id=12, @@ -110,6 +132,8 @@ Herta_BaseZone = MapPlane( en='Base Zone', jp='ベース部分', es='Zona de la base', + world_id=0, + plane_id=2000101, ) Herta_StorageZone = MapPlane( id=13, @@ -119,6 +143,8 @@ Herta_StorageZone = MapPlane( en='Storage Zone', jp='収容部分', es='Zona de almacenamiento', + world_id=0, + plane_id=2000201, ) Herta_SupplyZone = MapPlane( id=14, @@ -128,6 +154,8 @@ Herta_SupplyZone = MapPlane( en='Supply Zone', jp='サポート部分', es='Zona de suministros', + world_id=0, + plane_id=2000301, ) Herta_SeclusionZone = MapPlane( id=15, @@ -137,6 +165,8 @@ Herta_SeclusionZone = MapPlane( en='Seclusion Zone', jp='封鎖部分', es='Zona de confinamiento', + world_id=0, + plane_id=2000401, ) Jarilo_AdministrativeDistrict = MapPlane( id=16, @@ -146,6 +176,8 @@ Jarilo_AdministrativeDistrict = MapPlane( en='Administrative District', jp='行政区', es='Distrito administrativo', + world_id=1, + plane_id=1010101, ) Jarilo_OutlyingSnowPlains = MapPlane( id=17, @@ -155,6 +187,8 @@ Jarilo_OutlyingSnowPlains = MapPlane( en='Outlying Snow Plains', jp='郊外雪原', es='Llanuras nevadas de las afueras', + world_id=1, + plane_id=2010101, ) Jarilo_BackwaterPass = MapPlane( id=18, @@ -164,6 +198,8 @@ Jarilo_BackwaterPass = MapPlane( en='Backwater Pass', jp='外縁通路', es='Paso del Remanso', + world_id=1, + plane_id=2011101, ) Jarilo_SilvermaneGuardRestrictedZone = MapPlane( id=19, @@ -173,6 +209,8 @@ Jarilo_SilvermaneGuardRestrictedZone = MapPlane( en='Silvermane Guard Restricted Zone', jp='シルバーメイン禁区', es='Zona restringida de la Guardia Crinargenta', + world_id=1, + plane_id=2013101, ) Jarilo_CorridorofFadingEchoes = MapPlane( id=20, @@ -182,6 +220,8 @@ Jarilo_CorridorofFadingEchoes = MapPlane( en='Corridor of Fading Echoes', jp='残響回廊', es='Pasadizo de los ecos apagados', + world_id=1, + plane_id=2013201, ) Jarilo_EverwinterHill = MapPlane( id=21, @@ -191,6 +231,8 @@ Jarilo_EverwinterHill = MapPlane( en='Everwinter Hill', jp='常冬峰', es='Colina del Siempreinvierno', + world_id=1, + plane_id=2013401, ) Jarilo_PillarsofCreation = MapPlane( id=22, @@ -200,6 +242,8 @@ Jarilo_PillarsofCreation = MapPlane( en='Pillars of Creation', jp='造物の柱', es='Pilares de la Creación', + world_id=1, + plane_id=2013501, ) Jarilo_OldWeaponTestingGround = MapPlane( id=23, @@ -209,6 +253,8 @@ Jarilo_OldWeaponTestingGround = MapPlane( en='Old Weapon Testing Ground', jp='旧武器実験場', es='Antiguo campo de prueba de armas', + world_id=1, + plane_id=2013601, ) Jarilo_BoulderTown = MapPlane( id=24, @@ -218,6 +264,8 @@ Jarilo_BoulderTown = MapPlane( en='Boulder Town', jp='ボルダータウン', es='Villarroca', + world_id=1, + plane_id=1010201, ) Jarilo_GreatMine = MapPlane( id=25, @@ -227,6 +275,8 @@ Jarilo_GreatMine = MapPlane( en='Great Mine', jp='大鉱区', es='Mina principal', + world_id=1, + plane_id=2012101, ) Jarilo_RivetTown = MapPlane( id=26, @@ -236,6 +286,8 @@ Jarilo_RivetTown = MapPlane( en='Rivet Town', jp='リベットタウン', es='Villarremache', + world_id=1, + plane_id=2012201, ) Jarilo_RobotSettlement = MapPlane( id=27, @@ -245,6 +297,8 @@ Jarilo_RobotSettlement = MapPlane( en='Robot Settlement', jp='機械集落', es='Asentamiento robot', + world_id=1, + plane_id=2012301, ) Luofu_CentralStarskiffHaven = MapPlane( id=28, @@ -254,6 +308,8 @@ Luofu_CentralStarskiffHaven = MapPlane( en='Central Starskiff Haven', jp='星槎海中枢', es='Zona central de la Dársena de astroesquifes', + world_id=2, + plane_id=1020101, ) Luofu_Cloudford = MapPlane( id=29, @@ -263,6 +319,8 @@ Luofu_Cloudford = MapPlane( en='Cloudford', jp='流雲渡し', es='Vado de las Nubes', + world_id=2, + plane_id=2021101, ) Luofu_StargazerNavalia = MapPlane( id=30, @@ -272,6 +330,8 @@ Luofu_StargazerNavalia = MapPlane( en='Stargazer Navalia', jp='廻星港', es='Puerto Miraestrellas', + world_id=2, + plane_id=2021201, ) Luofu_ExaltingSanctum = MapPlane( id=31, @@ -281,6 +341,8 @@ Luofu_ExaltingSanctum = MapPlane( en='Exalting Sanctum', jp='長楽天', es='Sánctum de la Exaltación', + world_id=2, + plane_id=1020201, ) Luofu_AurumAlley = MapPlane( id=32, @@ -290,6 +352,8 @@ Luofu_AurumAlley = MapPlane( en='Aurum Alley', jp='金人巷', es='Callejón Aurum', + world_id=2, + plane_id=1020204, ) Luofu_DivinationCommission = MapPlane( id=33, @@ -299,6 +363,8 @@ Luofu_DivinationCommission = MapPlane( en='Divination Commission', jp='太卜司', es='Comisión de Adivinación', + world_id=2, + plane_id=2022101, ) Luofu_ArtisanshipCommission = MapPlane( id=34, @@ -308,6 +374,8 @@ Luofu_ArtisanshipCommission = MapPlane( en='Artisanship Commission', jp='工造司', es='Comisión de Artesanía', + world_id=2, + plane_id=2022201, ) Luofu_FyxestrollGarden = MapPlane( id=35, @@ -317,6 +385,8 @@ Luofu_FyxestrollGarden = MapPlane( en='Fyxestroll Garden', jp='綏園', es='Jardín del Sosiego', + world_id=2, + plane_id=2022301, ) Luofu_AlchemyCommission = MapPlane( id=36, @@ -326,6 +396,8 @@ Luofu_AlchemyCommission = MapPlane( en='Alchemy Commission', jp='丹鼎司', es='Comisión de Alquimia', + world_id=2, + plane_id=2023101, ) Luofu_ScalegorgeWaterscape = MapPlane( id=37, @@ -335,4 +407,61 @@ Luofu_ScalegorgeWaterscape = MapPlane( en='Scalegorge Waterscape', jp='鱗淵境', es='Desfiladero de Escamas', + world_id=2, + plane_id=2023201, +) +Penacony_TheReverieReality = MapPlane( + id=38, + name='Penacony_TheReverieReality', + cn='「白日梦」酒店-现实', + cht='「白日夢」飯店-現實', + en='The Reverie (Reality)', + jp='ホテル・レバリー-現実', + es='Hotel Fantasía (realidad)', + world_id=3, + plane_id=1030501, +) +Penacony_GoldenHour = MapPlane( + id=39, + name='Penacony_GoldenHour', + cn='黄金的时刻', + cht='黃金的時刻', + en='Golden Hour', + jp='黄金の刻', + es='Momento Dorado', + world_id=3, + plane_id=1030101, +) +Penacony_DreamEdge = MapPlane( + id=40, + name='Penacony_DreamEdge', + cn='筑梦边境', + cht='築夢邊境', + en="Dream's Edge", + jp='ドリームボーダー', + es='Frontera de los Sueños', + world_id=3, + plane_id=2031301, +) +Penacony_AChildDream = MapPlane( + id=41, + name='Penacony_AChildDream', + cn='稚子的梦', + cht='稚子的夢', + en="A Child's Dream", + jp='稚児の夢', + es='Sueño infantil', + world_id=3, + plane_id=2031201, +) +Penacony_TheReverieDreamscape = MapPlane( + id=42, + name='Penacony_TheReverieDreamscape', + cn='「白日梦」酒店-梦境', + cht='「白日夢」飯店-夢境', + en='The Reverie (Dreamscape)', + jp='ホテル・レバリー-夢境', + es='Hotel Fantasía (paisaje onírico)', + world_id=3, + plane_id=2031101, ) diff --git a/tasks/map/keywords/world.py b/tasks/map/keywords/world.py index 3cb773450..76b8939b9 100644 --- a/tasks/map/keywords/world.py +++ b/tasks/map/keywords/world.py @@ -11,6 +11,8 @@ Herta_Space_Station = MapWorld( en='Herta Space Station', jp='宇宙ステーション「ヘルタ」', es='Estación Espacial Herta', + world_id=0, + short_name='Herta', ) Jarilo_VI = MapWorld( id=2, @@ -20,6 +22,8 @@ Jarilo_VI = MapWorld( en='Jarilo-VI', jp='ヤリーロ-VI', es='Jarilo-VI', + world_id=1, + short_name='Jarilo', ) The_Xianzhou_Luofu = MapWorld( id=3, @@ -29,4 +33,17 @@ The_Xianzhou_Luofu = MapWorld( en='The Xianzhou Luofu', jp='仙舟「羅浮」', es='El Luofu de Xianzhou', + world_id=2, + short_name='Luofu', +) +Penacony = MapWorld( + id=4, + name='Penacony', + cn='匹诺康尼', + cht='匹諾康尼', + en='Penacony', + jp='ピノコニー', + es='Colonipenal', + world_id=3, + short_name='Penacony', ) diff --git a/tasks/map/minimap/minimap.py b/tasks/map/minimap/minimap.py index 86fd52f2f..ce6a78c16 100644 --- a/tasks/map/minimap/minimap.py +++ b/tasks/map/minimap/minimap.py @@ -438,13 +438,13 @@ if __name__ == '__main__': # MapResource.SRCMAP = '../srcmap/srcmap' self = Minimap() # Set plane, assume starting from Jarilo_AdministrativeDistrict - self.set_plane('Jarilo_BackwaterPass', floor='F1') + self.set_plane('Jarilo_SilvermaneGuardRestrictedZone', floor='F1') ui = UI('src') ui.device.disable_stuck_detection() # Set starter point. Starter point will be calculated if it's missing but may contain errors. # With starter point set, position is only searched around starter point and new position becomes new starter point. - # self.init_position((337, 480)) + self.init_position((227.7, 425.5), locked=True) while 1: ui.device.screenshot() self.update(ui.device.image) diff --git a/tasks/map/resource/resource.py b/tasks/map/resource/resource.py index 3e9001997..2411e00e3 100644 --- a/tasks/map/resource/resource.py +++ b/tasks/map/resource/resource.py @@ -79,9 +79,9 @@ class MapResource(ResourceConst): @cached_property def assets_file_basename(self): if self.plane.has_multiple_floors or self.is_special_plane: - return f'./position/{self.plane.world}/{self.plane.name}_{self.floor}' + return f'./position/{self.plane.world.short_name}/{self.plane.name}_{self.floor}' else: - return f'./position/{self.plane.world}/{self.plane.name}' + return f'./position/{self.plane.world.short_name}/{self.plane.name}' @cached_property def assets_floor(self): diff --git a/tasks/rogue/assets/assets_rogue_entry.py b/tasks/rogue/assets/assets_rogue_entry.py index f67636b75..4b310a520 100644 --- a/tasks/rogue/assets/assets_rogue_entry.py +++ b/tasks/rogue/assets/assets_rogue_entry.py @@ -27,10 +27,10 @@ OCR_WORLD = ButtonWrapper( name='OCR_WORLD', share=Button( file='./assets/share/rogue/entry/OCR_WORLD.png', - area=(488, 339, 718, 371), - search=(468, 319, 738, 391), - color=(45, 44, 68), - button=(488, 339, 718, 371), + area=(488, 339, 718, 395), + search=(468, 319, 738, 415), + color=(38, 35, 64), + button=(488, 339, 718, 395), ), ) THEME_DLC = ButtonWrapper( diff --git a/tasks/rogue/entry/entry.py b/tasks/rogue/entry/entry.py index c3bc9b4a4..4a7bd2410 100644 --- a/tasks/rogue/entry/entry.py +++ b/tasks/rogue/entry/entry.py @@ -1,7 +1,11 @@ import re from datetime import datetime, timedelta +import cv2 +import numpy as np + from module.base.timer import Timer +from module.base.utils import color_similarity_2d from module.exception import RequestHumanTakeover, ScriptError from module.logger import logger from module.ocr.ocr import Ocr @@ -67,6 +71,28 @@ def chinese_to_arabic(chinese_number: str) -> int: class OcrRogueWorld(Ocr): + def pre_process(self, image): + # Letter randomly moving up and down + # Crop to the up/down border of the white letter + center = color_similarity_2d(image, color=(255, 255, 255)) + cv2.inRange(center, 180, 255, dst=center) + # print(np.count_nonzero(center, axis=1)) + # World 8 + # [ 0 0 0 0 0 0 0 2 23 24 22 21 23 29 44 47 38 37 31 32 33 33 31 34 + # 34 44 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + # 0 0 0 0 0 0 0 0] + # In Progress + # World 8 + # [ 0 0 0 1 0 3 6 5 3 3 3 1 2 0 0 1 2 0 0 0 0 0 0 0 + # 0 0 0 2 22 24 22 21 23 29 45 46 39 36 30 32 32 32 31 34 34 44 34 0 + # 0 0 0 0 0 0 0 0] + center = np.where(np.count_nonzero(center, axis=1) > 10)[0] + if len(center) < 2: + return image + up, down = center[0], center[-1] + image = image[up:down, :, :] + return image + def format_result(self, result: str) -> int: res = re.search(r'第([一二三四五六七八九十])世界', result) if res: diff --git a/tasks/rogue/keywords/curio.py b/tasks/rogue/keywords/curio.py index bfd7fedf3..87407f3d2 100644 --- a/tasks/rogue/keywords/curio.py +++ b/tasks/rogue/keywords/curio.py @@ -486,7 +486,7 @@ Fissured_Cuckoo_Clock = RogueCurio( cn='分裂咕咕钟', cht='分裂咕咕鐘', en='Fissured Cuckoo Clock', - jp='分裂鳩時計', + jp='機械式鳩時計', es='Reloj de cuco agrietado', ) Typical_Genius_Society_Gossip = RogueCurio( diff --git a/tasks/rogue/keywords/event_option.py b/tasks/rogue/keywords/event_option.py index c11560faa..f18d18677 100644 --- a/tasks/rogue/keywords/event_option.py +++ b/tasks/rogue/keywords/event_option.py @@ -441,8 +441,8 @@ You_re_not_a_reliable_investment_manager = RogueEventOption( cn='你不是一个值得信任的*投资经理*。', cht='你不是一個值得信任的*投資經理*。', en='You\'re not a reliable "investment manager."', - jp='{F#あんた}{M#お前}は信頼できる※ファンドマネージャー※ではない', - es='No eres {F#una}{M#un} "{F#gestora}{M#gestor} de inversiones" fiable.', + jp='は信頼できる※ファンドマネージャー※ではない', + es='No eres " de inversiones" fiable.', ) I_hate_this_era = RogueEventOption( id=50, @@ -1765,7 +1765,7 @@ Hide_under_the_boat_together = RogueEventOption( cht='一起躲在船底。', en='Hide under the boat together.', jp='一緒に船底に隠れる', - es='Escóndanse junt{F#as}{M#os} debajo del bote.', + es='Escóndanse junt debajo del bote.', ) Bottoms_up = RogueEventOption( id=197, @@ -2179,7 +2179,7 @@ Release_them_together_from_the_pain = RogueEventOption( cht='將牠們一併從「痛苦」中釋放。', en='Release them together from the "pain."', jp='彼らをまとめて「苦痛」から解放する', - es='Libéral{F#as}{M#os} junt{F#as}{M#os} del "dolor".', + es='Libéral junt del "dolor".', ) Give_the_adult_beast_a_send_off = RogueEventOption( id=243, @@ -2988,7 +2988,7 @@ Adjust_Intra_Cognition_I_am_organic = RogueEventOption( cn='调整「自我认知」-我是有机。', cht='調整「自我認知」-我是有機。', en='Adjust Intra-Cognition — I am organic.', - jp='「自己認識」を調整-{F#私}{M#俺}は有機生命体', + jp='「自己認識」を調整-は有機生命体', es='Ajusta tu autopercepción: soy orgánico.', ) Adjust_Intra_Cognition_I_am_inorganic = RogueEventOption( @@ -2997,7 +2997,7 @@ Adjust_Intra_Cognition_I_am_inorganic = RogueEventOption( cn='调整「自我认知」-我是无机。', cht='調整「自我認知」-我是無機。', en='Adjust Intra-Cognition — I am inorganic.', - jp='「自己認識」を調整-{F#私}{M#俺}は無機生命体', + jp='「自己認識」を調整-は無機生命体', es='Ajusta tu autopercepción: soy inorgánico.', ) Pick_a_family_element = RogueEventOption( @@ -3214,5 +3214,5 @@ Forced_to_fight = RogueEventOption( cht='被迫戰鬥。', en='Forced to fight.', jp='戦闘を強いられる', - es='Obligad{F#a}{M#o} a combatir.', + es='Obligad a combatir.', ) diff --git a/tasks/rogue/keywords/event_title.py b/tasks/rogue/keywords/event_title.py index 6b03050d9..86490d346 100644 --- a/tasks/rogue/keywords/event_title.py +++ b/tasks/rogue/keywords/event_title.py @@ -199,7 +199,7 @@ Cosmic_Altruist_Part_3 = RogueEventTitle( cn='银河好人(其三)', cht='銀河好人(其三)', en='Cosmic Altruist (Part 3)', - jp='銀河のお人好し(その3)', + jp='銀河のお人よし(その3)', es='Altruismo galáctico (III)', option_ids=[81, 82, 83, 84, 85], ) @@ -269,7 +269,7 @@ We_Are_Cowboys = RogueEventTitle( cn='我们是牛仔', cht='我們是牛仔', en='We Are Cowboys', - jp='俺たちカウボーイ', + jp='僕たちカウボーイ', es='Somos vaqueros', option_ids=[104, 105, 106, 107, 108], ) @@ -879,7 +879,7 @@ The_Perfect_Grand_Challenge = RogueEventTitle( cn='*完美*大挑战!', cht='*完美*大挑戰!', en='The *Perfect* Grand Challenge!', - jp='※完璧※大挑戦!', + jp='「完璧」大挑戦!', es='¡El gran desafío perfecto!', option_ids=[142, 258, 259, 260, 261], ) diff --git a/tasks/rogue/rogue.py b/tasks/rogue/rogue.py index a6f1a2984..7635b25b8 100644 --- a/tasks/rogue/rogue.py +++ b/tasks/rogue/rogue.py @@ -1,5 +1,5 @@ from module.logger import logger -from tasks.battle_pass.keywords import KEYWORD_BATTLE_PASS_QUEST +from tasks.battle_pass.keywords import KEYWORDS_BATTLE_PASS_QUEST from tasks.daily.keywords import KEYWORDS_DAILY_QUEST from tasks.rogue.entry.entry import RogueEntry from tasks.rogue.exception import RogueReachedWeeklyPointLimit, RogueTeamNotPrepared @@ -54,7 +54,7 @@ class Rogue(RouteLoader, RogueEntry): self.config.task_call('DailyQuest') self.config.task_stop() quests = self.config.stored.BattlePassWeeklyQuest.load_quests() - if KEYWORD_BATTLE_PASS_QUEST.Complete_Simulated_Universe_1_times in quests: + if KEYWORDS_BATTLE_PASS_QUEST.Complete_Simulated_Universe_1_times in quests: logger.info('Achieve battle pass quest Complete_Simulated_Universe_1_times') self.config.task_call('BattlePass') self.config.task_stop()