diff --git a/assets/character/Feixiao.png b/assets/character/Feixiao.png new file mode 100644 index 000000000..4bf1b51da Binary files /dev/null and b/assets/character/Feixiao.png differ diff --git a/assets/character/Moze.png b/assets/character/Moze.png new file mode 100644 index 000000000..c150737af Binary files /dev/null and b/assets/character/Moze.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_3.png b/assets/share/dungeon/ui/CALYX_WORLD_3.png deleted file mode 100644 index eeb73049b..000000000 Binary files a/assets/share/dungeon/ui/CALYX_WORLD_3.png and /dev/null differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_1.png b/assets/share/dungeon/ui_list/LIST_ASCENDING.png similarity index 75% rename from assets/share/dungeon/ui/CALYX_WORLD_1.png rename to assets/share/dungeon/ui_list/LIST_ASCENDING.png index 5457292d2..f6f6a8d8d 100644 Binary files a/assets/share/dungeon/ui/CALYX_WORLD_1.png and b/assets/share/dungeon/ui_list/LIST_ASCENDING.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_2.png b/assets/share/dungeon/ui_list/LIST_DESCENDING.png similarity index 73% rename from assets/share/dungeon/ui/CALYX_WORLD_2.png rename to assets/share/dungeon/ui_list/LIST_DESCENDING.png index 3b3e3edb7..3d34041c7 100644 Binary files a/assets/share/dungeon/ui/CALYX_WORLD_2.png and b/assets/share/dungeon/ui_list/LIST_DESCENDING.png differ diff --git a/assets/share/dungeon/ui/OCR_DUNGEON_LIST.BUTTON.png b/assets/share/dungeon/ui_list/OCR_DUNGEON_LIST.BUTTON.png similarity index 100% rename from assets/share/dungeon/ui/OCR_DUNGEON_LIST.BUTTON.png rename to assets/share/dungeon/ui_list/OCR_DUNGEON_LIST.BUTTON.png diff --git a/assets/share/dungeon/ui/OCR_DUNGEON_LIST.png b/assets/share/dungeon/ui_list/OCR_DUNGEON_LIST.png similarity index 100% rename from assets/share/dungeon/ui/OCR_DUNGEON_LIST.png rename to assets/share/dungeon/ui_list/OCR_DUNGEON_LIST.png diff --git a/assets/share/dungeon/ui_list/OCR_DUNGEON_NAME.png b/assets/share/dungeon/ui_list/OCR_DUNGEON_NAME.png new file mode 100644 index 000000000..4346f1da1 Binary files /dev/null and b/assets/share/dungeon/ui_list/OCR_DUNGEON_NAME.png differ diff --git a/assets/share/dungeon/ui_list/OCR_DUNGEON_NAME_ROGUE.png b/assets/share/dungeon/ui_list/OCR_DUNGEON_NAME_ROGUE.png new file mode 100644 index 000000000..3dd619f00 Binary files /dev/null and b/assets/share/dungeon/ui_list/OCR_DUNGEON_NAME_ROGUE.png differ diff --git a/assets/share/dungeon/ui_list/OCR_DUNGEON_TELEPORT.png b/assets/share/dungeon/ui_list/OCR_DUNGEON_TELEPORT.png new file mode 100644 index 000000000..5c1c74d8a Binary files /dev/null and b/assets/share/dungeon/ui_list/OCR_DUNGEON_TELEPORT.png differ diff --git a/config/template.json b/config/template.json index 393ec9360..83476d5ab 100644 --- a/config/template.json +++ b/config/template.json @@ -65,6 +65,8 @@ "Item_IPC_Work_Permit": {}, "Item_Raging_Heart": {}, "Item_Dream_Fridge": {}, + "Item_Nail_of_the_Beast_Coffin": {}, + "Item_A_Glass_of_the_Besotted_Era": {}, "Item_Dream_Flamer": {}, "Item_Worldbreaker_Blade": {}, "Item_Arrow_of_the_Starchaser": {}, @@ -86,6 +88,7 @@ "Item_Regret_of_Infinite_Ochema": {}, "Item_Past_Evils_of_the_Borehole_Planet_Disaster": {}, "Item_Lost_Echo_of_the_Shared_Wish": {}, + "Item_Auspice_Sliver": {}, "Item_Squirming_Core": {}, "Item_Conqueror_Will": {}, "Item_Silvermane_Medal": {}, diff --git a/dev_tools/keywords/dungeon_list.py b/dev_tools/keywords/dungeon_list.py index 658ef4bdf..93403a078 100644 --- a/dev_tools/keywords/dungeon_list.py +++ b/dev_tools/keywords/dungeon_list.py @@ -73,6 +73,12 @@ class GenerateDungeonList(GenerateKeyword): # Add plane suffix from tasks.map.keywords import MapPlane + if text.startswith('Calyx_Golden'): + plane = MapPlane.find_plane_id(keyword['plane_id']) + if plane is not None: + text = f'{text}_{plane.world.name}' + else: + text = f'{text}_unknown_world' if text.startswith('Calyx_Crimson'): plane = MapPlane.find_plane_id(keyword['plane_id']) if plane is not None: @@ -110,16 +116,33 @@ class GenerateDungeonList(GenerateKeyword): dungeons = [d for d in dungeons if not condition(d)] dungeons = calyx + dungeons - # Reverse Divergent_Universe - start = 0 - end = 0 - for index, dungeon in enumerate(dungeons): - if dungeon['name'].startswith('Divergent_Universe'): - if start == 0: - start = index - end = index + 1 - if start > 0 and end > 0: - dungeons = dungeons[:start] + dungeons[start:end][::-1] + dungeons[end:] + # 2024.09.10, v2.5, add genre prefix + for dungeon in dungeons: + if 230 <= dungeon['dungeon_id'] < 1000: + dungeon['name'] = 'Divergent_Universe_' + dungeon['name'] + if 100 < dungeon['dungeon_id'] < 200: + dungeon['name'] = 'Simulated_Universe_' + dungeon['name'] + + # Reverse dungeon list, latest at top + def reverse_on_name(d, prefix): + start = 0 + end = 0 + for index, dungeon in enumerate(d): + if dungeon['name'].startswith(prefix): + if start == 0: + start = index + end = index + 1 + if start > 0 and end > 0: + d = d[:start] + d[start:end][::-1] + d[end:] + return d + + dungeons = reverse_on_name(dungeons, 'Divergent_Universe') + dungeons = reverse_on_name(dungeons, 'Cavern_of_Corrosion') + dungeons = reverse_on_name(dungeons, 'Echo_of_War') + + # Reverse Calyx_Golden, sort by world + # Poor sort + dungeons[0:3], dungeons[6:9] = dungeons[6:9], dungeons[0:3] # Re-sort ID self.keyword_index = 0 diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 120a5c862..de7767dfb 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -340,6 +340,18 @@ "display": "display", "stored": "StoredPlanner" }, + "Item_Nail_of_the_Beast_Coffin": { + "type": "planner", + "value": {}, + "display": "display", + "stored": "StoredPlanner" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "type": "planner", + "value": {}, + "display": "display", + "stored": "StoredPlanner" + }, "Item_Dream_Flamer": { "type": "planner", "value": {}, @@ -466,6 +478,12 @@ "display": "display", "stored": "StoredPlanner" }, + "Item_Auspice_Sliver": { + "type": "planner", + "value": {}, + "display": "display", + "stored": "StoredPlanner" + }, "Item_Squirming_Core": { "type": "planner", "value": {}, @@ -554,8 +572,10 @@ "Stagnant_Shadow_Nectar", "Stagnant_Shadow_Fulmination", "Stagnant_Shadow_Doom", + "Stagnant_Shadow_Mechwolf", "Stagnant_Shadow_Gust", "Stagnant_Shadow_Celestial", + "Stagnant_Shadow_Gloam", "Stagnant_Shadow_Quanta", "Stagnant_Shadow_Abomination", "Stagnant_Shadow_Roast", @@ -662,6 +682,7 @@ "DanHeng", "DanHengImbibitorLunae", "DrRatio", + "Feixiao", "Firefly", "FuXuan", "Gallagher", @@ -683,6 +704,7 @@ "March7thPreservation", "March7thTheHunt", "Misha", + "Moze", "Natasha", "Pela", "Qingque", @@ -795,6 +817,7 @@ "type": "select", "value": "Divergent_Universe_Eternal_Comedy", "option": [ + "Divergent_Universe_Famished_Worker", "Divergent_Universe_Eternal_Comedy", "Divergent_Universe_To_Sweet_Dreams", "Divergent_Universe_Pouring_Blades", @@ -858,6 +881,7 @@ "DanHeng", "DanHengImbibitorLunae", "DrRatio", + "Feixiao", "Firefly", "FuXuan", "Gallagher", @@ -879,6 +903,7 @@ "March7thPreservation", "March7thTheHunt", "Misha", + "Moze", "Natasha", "Pela", "Qingque", @@ -1345,7 +1370,8 @@ "Echo_of_War_End_of_the_Eternal_Freeze", "Echo_of_War_Divine_Seed", "Echo_of_War_Borehole_Planet_Old_Crater", - "Echo_of_War_Salutations_of_Ashen_Dreams" + "Echo_of_War_Salutations_of_Ashen_Dreams", + "Echo_of_War_Inner_Beast_Battlefield" ] }, "Team": { @@ -1392,6 +1418,7 @@ "DanHeng", "DanHengImbibitorLunae", "DrRatio", + "Feixiao", "Firefly", "FuXuan", "Gallagher", @@ -1413,6 +1440,7 @@ "March7thPreservation", "March7thTheHunt", "Misha", + "Moze", "Natasha", "Pela", "Qingque", diff --git a/module/config/argument/stored.json b/module/config/argument/stored.json index 33511775d..060c4cb1a 100644 --- a/module/config/argument/stored.json +++ b/module/config/argument/stored.json @@ -343,6 +343,28 @@ "order": 0, "color": "#777777" }, + "Item_Nail_of_the_Beast_Coffin": { + "name": "Item_Nail_of_the_Beast_Coffin", + "path": "Dungeon.Planner.Item_Nail_of_the_Beast_Coffin", + "i18n": "Planner.Item_Nail_of_the_Beast_Coffin.name", + "stored": "StoredPlanner", + "attrs": { + "time": "2020-01-01 00:00:00" + }, + "order": 0, + "color": "#777777" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "name": "Item_A_Glass_of_the_Besotted_Era", + "path": "Dungeon.Planner.Item_A_Glass_of_the_Besotted_Era", + "i18n": "Planner.Item_A_Glass_of_the_Besotted_Era.name", + "stored": "StoredPlanner", + "attrs": { + "time": "2020-01-01 00:00:00" + }, + "order": 0, + "color": "#777777" + }, "Item_Dream_Flamer": { "name": "Item_Dream_Flamer", "path": "Dungeon.Planner.Item_Dream_Flamer", @@ -574,6 +596,17 @@ "order": 0, "color": "#777777" }, + "Item_Auspice_Sliver": { + "name": "Item_Auspice_Sliver", + "path": "Dungeon.Planner.Item_Auspice_Sliver", + "i18n": "Planner.Item_Auspice_Sliver.name", + "stored": "StoredPlanner", + "attrs": { + "time": "2020-01-01 00:00:00" + }, + "order": 0, + "color": "#777777" + }, "Item_Squirming_Core": { "name": "Item_Squirming_Core", "path": "Dungeon.Planner.Item_Squirming_Core", diff --git a/module/config/config_generated.py b/module/config/config_generated.py index e6a45728f..c8db44b15 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -41,7 +41,7 @@ class GeneratedConfig: Optimization_WhenTaskQueueEmpty = 'goto_main' # stay_there, goto_main, close_game # Group `Dungeon` - Dungeon_Name = 'Calyx_Golden_Treasures_Jarilo_VI' # 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_Preservation_Penacony_ClockStudiosThemePark, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Abundance_Luofu_FyxestrollGarden, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater, 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_Duty, Stagnant_Shadow_Blaze, Stagnant_Shadow_Scorch, Stagnant_Shadow_Ire, 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, Cavern_of_Corrosion_Path_of_Cavalier + Dungeon_Name = 'Calyx_Golden_Treasures_Jarilo_VI' # 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_Preservation_Penacony_ClockStudiosThemePark, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Abundance_Luofu_FyxestrollGarden, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater, 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_Duty, Stagnant_Shadow_Blaze, Stagnant_Shadow_Scorch, Stagnant_Shadow_Ire, Stagnant_Shadow_Rime, Stagnant_Shadow_Icicle, Stagnant_Shadow_Nectar, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Doom, Stagnant_Shadow_Mechwolf, Stagnant_Shadow_Gust, Stagnant_Shadow_Celestial, Stagnant_Shadow_Gloam, 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, Cavern_of_Corrosion_Path_of_Cavalier Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures_Jarilo_VI' # 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_Preservation_Penacony_ClockStudiosThemePark, Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains, Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue, Calyx_Crimson_Abundance_Jarilo_BackwaterPass, Calyx_Crimson_Abundance_Luofu_FyxestrollGarden, Calyx_Crimson_Erudition_Jarilo_RivetTown, Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater, 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' # 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, Cavern_of_Corrosion_Path_of_Cavalier Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6, 7, 8, 9 @@ -53,7 +53,7 @@ class GeneratedConfig: # Group `DungeonSupport` DungeonSupport_Use = 'when_daily' # always_use, when_daily, do_not_use - DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Acheron, Argenti, Arlan, Asta, Aventurine, Bailu, BlackSwan, Blade, Boothill, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, Firefly, FuXuan, Gallagher, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, Jade, Jiaoqiu, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7thPreservation, March7thTheHunt, Misha, Natasha, Pela, Qingque, Robin, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerHarmony, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong, Yunli + DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Acheron, Argenti, Arlan, Asta, Aventurine, Bailu, BlackSwan, Blade, Boothill, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, Feixiao, Firefly, FuXuan, Gallagher, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, Jade, Jiaoqiu, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7thPreservation, March7thTheHunt, Misha, Moze, Natasha, Pela, Qingque, Robin, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerHarmony, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong, Yunli # Group `DungeonStorage` DungeonStorage_TrailblazePower = {} @@ -90,6 +90,8 @@ class GeneratedConfig: Planner_Item_IPC_Work_Permit = {} Planner_Item_Raging_Heart = {} Planner_Item_Dream_Fridge = {} + Planner_Item_Nail_of_the_Beast_Coffin = {} + Planner_Item_A_Glass_of_the_Besotted_Era = {} Planner_Item_Dream_Flamer = {} Planner_Item_Worldbreaker_Blade = {} Planner_Item_Arrow_of_the_Starchaser = {} @@ -111,6 +113,7 @@ class GeneratedConfig: Planner_Item_Regret_of_Infinite_Ochema = {} Planner_Item_Past_Evils_of_the_Borehole_Planet_Disaster = {} Planner_Item_Lost_Echo_of_the_Shared_Wish = {} + Planner_Item_Auspice_Sliver = {} Planner_Item_Squirming_Core = {} Planner_Item_Conqueror_Will = {} Planner_Item_Silvermane_Medal = {} @@ -121,7 +124,7 @@ class GeneratedConfig: Planner_Item_Shards_of_Desires = {} # Group `Weekly` - Weekly_Name = 'Echo_of_War_Divine_Seed' # Echo_of_War_Destruction_Beginning, Echo_of_War_End_of_the_Eternal_Freeze, Echo_of_War_Divine_Seed, Echo_of_War_Borehole_Planet_Old_Crater, Echo_of_War_Salutations_of_Ashen_Dreams + Weekly_Name = 'Echo_of_War_Divine_Seed' # Echo_of_War_Destruction_Beginning, Echo_of_War_End_of_the_Eternal_Freeze, Echo_of_War_Divine_Seed, Echo_of_War_Borehole_Planet_Old_Crater, Echo_of_War_Salutations_of_Ashen_Dreams, Echo_of_War_Inner_Beast_Battlefield Weekly_Team = 1 # 1, 2, 3, 4, 5, 6, 7, 8, 9 # Group `DailyStorage` @@ -182,7 +185,7 @@ class GeneratedConfig: RogueDebug_DebugMode = False # Group `Ornament` - Ornament_Dungeon = 'Divergent_Universe_Eternal_Comedy' # Divergent_Universe_Eternal_Comedy, Divergent_Universe_To_Sweet_Dreams, Divergent_Universe_Pouring_Blades, Divergent_Universe_Fruit_of_Evil, Divergent_Universe_Permafrost, Divergent_Universe_Gentle_Words, Divergent_Universe_Smelted_Heart, Divergent_Universe_Untoppled_Walls + Ornament_Dungeon = 'Divergent_Universe_Eternal_Comedy' # Divergent_Universe_Famished_Worker, Divergent_Universe_Eternal_Comedy, Divergent_Universe_To_Sweet_Dreams, Divergent_Universe_Pouring_Blades, Divergent_Universe_Fruit_of_Evil, Divergent_Universe_Permafrost, Divergent_Universe_Gentle_Words, Divergent_Universe_Smelted_Heart, Divergent_Universe_Untoppled_Walls Ornament_UseImmersifier = True # True Ornament_DoubleEvent = True # True Ornament_UseStamina = False diff --git a/module/config/config_updater.py b/module/config/config_updater.py index a8ada2eac..c820c2694 100644 --- a/module/config/config_updater.py +++ b/module/config/config_updater.py @@ -100,7 +100,7 @@ class ConfigGenerator: option_add(keys='Ornament.Dungeon.option', options=ornament) # Insert characters from tasks.character.keywords import CharacterList - unsupported_characters = [] + unsupported_characters = ['Lingsha'] characters = [character.name for character in CharacterList.instances.values() if character.name not in unsupported_characters] option_add(keys='DungeonSupport.Character.option', options=characters) diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 95253347d..16eb04767 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -238,15 +238,15 @@ "Name": { "name": "Dungeon Name", "help": "Default dungeon setting", - "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_Golden_Memories_Jarilo_VI": "Material: Character EXP (Bud of Memories)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: Character EXP (Bud of Memories)", + "Calyx_Golden_Memories_Penacony": "Material: Character EXP (Bud of Memories)", + "Calyx_Golden_Aether_Jarilo_VI": "Material: Light Cone EXP (Bud of Aether)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: Light Cone EXP (Bud of Aether)", + "Calyx_Golden_Aether_Penacony": "Material: Light Cone EXP (Bud of Aether)", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Credit (Bud of Treasures)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Credit (Bud of Treasures)", + "Calyx_Golden_Treasures_Penacony": "Material: Credit (Bud of Treasures)", "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)", @@ -266,14 +266,16 @@ "Stagnant_Shadow_Duty": "Ascension: Physical (Boothill / Robin / Yunli)", "Stagnant_Shadow_Blaze": "Ascension: Fire (Himeko / Asta / Hook)", "Stagnant_Shadow_Scorch": "Ascension: Fire (Guinaifen / Topaz & Numby)", - "Stagnant_Shadow_Ire": "Ascension: Fire (Firefly / Gallagher / Jiaoqiu)", + "Stagnant_Shadow_Ire": "Ascension: Fire (Firefly / Gallagher / Jiaoqiu / Lingsha)", "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 / Acheron)", + "Stagnant_Shadow_Mechwolf": "Ascension: Lightning (Moze)", "Stagnant_Shadow_Gust": "Ascension: Wind (Dan Heng / Bronya / Sampo)", "Stagnant_Shadow_Celestial": "Ascension: Wind (Blade / Huohuo / Black Swan)", + "Stagnant_Shadow_Gloam": "Ascension: Wind (Feixiao)", "Stagnant_Shadow_Quanta": "Ascension: Quantum (Silver Wolf / Seele / Qingque)", "Stagnant_Shadow_Abomination": "Ascension: Quantum (Lynx / Fu Xuan / Xueyi)", "Stagnant_Shadow_Roast": "Ascension: Quantum (Jade / Sparkle)", @@ -293,15 +295,15 @@ "NameAtDoubleCalyx": { "name": "At Double Calyx Event, choose dungeon", "help": "Return to the default dungeon settings after double times exhausted", - "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_Golden_Memories_Jarilo_VI": "Material: Character EXP (Bud of Memories)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: Character EXP (Bud of Memories)", + "Calyx_Golden_Memories_Penacony": "Material: Character EXP (Bud of Memories)", + "Calyx_Golden_Aether_Jarilo_VI": "Material: Light Cone EXP (Bud of Aether)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: Light Cone EXP (Bud of Aether)", + "Calyx_Golden_Aether_Penacony": "Material: Light Cone EXP (Bud of Aether)", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Credit (Bud of Treasures)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Credit (Bud of Treasures)", + "Calyx_Golden_Treasures_Penacony": "Material: Credit (Bud of Treasures)", "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)", @@ -393,6 +395,7 @@ "DanHeng": "Dan Heng", "DanHengImbibitorLunae": "Dan Heng • Imbibitor Lunae", "DrRatio": "Dr. Ratio", + "Feixiao": "Feixiao", "Firefly": "Firefly", "FuXuan": "Fu Xuan", "Gallagher": "Gallagher", @@ -414,6 +417,7 @@ "March7thPreservation": "March 7th: Preservation", "March7thTheHunt": "March 7th: The Hunt", "Misha": "Misha", + "Moze": "Moze", "Natasha": "Natasha", "Pela": "Pela", "Qingque": "Qingque", @@ -567,13 +571,21 @@ "help": "" }, "Item_Raging_Heart": { - "name": "Ascension: Fire (Firefly / Gallagher / Jiaoqiu)", + "name": "Ascension: Fire (Firefly / Gallagher / Jiaoqiu / Lingsha)", "help": "" }, "Item_Dream_Fridge": { "name": "Ascension: Ice (Misha)", "help": "" }, + "Item_Nail_of_the_Beast_Coffin": { + "name": "Ascension: Lightning (Moze)", + "help": "" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "name": "Ascension: Wind (Feixiao)", + "help": "" + }, "Item_Dream_Flamer": { "name": "Ascension: Quantum (Jade / Sparkle)", "help": "" @@ -658,6 +670,10 @@ "name": "Salutations of Ashen Dreams (Penacony)", "help": "" }, + "Item_Auspice_Sliver": { + "name": "Inner Beast's Battlefield (The Xianzhou Luofu)", + "help": "" + }, "Item_Squirming_Core": { "name": "Squirming Core", "help": "" @@ -703,7 +719,8 @@ "Echo_of_War_End_of_the_Eternal_Freeze": "End of the Eternal Freeze (Jarilo-VI)", "Echo_of_War_Divine_Seed": "Divine Seed (The Xianzhou Luofu)", "Echo_of_War_Borehole_Planet_Old_Crater": "Borehole Planet's Old Crater (Herta Space Station)", - "Echo_of_War_Salutations_of_Ashen_Dreams": "Salutations of Ashen Dreams (Penacony)" + "Echo_of_War_Salutations_of_Ashen_Dreams": "Salutations of Ashen Dreams (Penacony)", + "Echo_of_War_Inner_Beast_Battlefield": "Inner Beast's Battlefield (The Xianzhou Luofu)" }, "Team": { "name": "Dungeon Team", @@ -933,11 +950,11 @@ "World": { "name": "World", "help": "", - "Simulated_Universe_World_3": "Simulated Universe: World 3", - "Simulated_Universe_World_4": "Simulated Universe: World 4", - "Simulated_Universe_World_5": "Simulated Universe: World 5", - "Simulated_Universe_World_6": "Simulated Universe: World 6", - "Simulated_Universe_World_8": "Simulated Universe: World 8" + "Simulated_Universe_World_3": "World 3", + "Simulated_Universe_World_4": "World 4", + "Simulated_Universe_World_5": "World 5", + "Simulated_Universe_World_6": "World 6", + "Simulated_Universe_World_8": "World 8" }, "Path": { "name": "Path", @@ -1047,6 +1064,7 @@ "Dungeon": { "name": "Dungeon Name", "help": "", + "Divergent_Universe_Famished_Worker": "Divergent_Universe_Famished_Worker (Famished Worker)", "Divergent_Universe_Eternal_Comedy": "Running Wolves & Kalpagni Lantern (Eternal Comedy)", "Divergent_Universe_To_Sweet_Dreams": "Sigonia & Izumo Gensei (To Sweet Dreams)", "Divergent_Universe_Pouring_Blades": "Firmament & Penacony (Pouring Blades)", diff --git a/module/config/i18n/es-ES.json b/module/config/i18n/es-ES.json index 7170aceb6..3ba57c747 100644 --- a/module/config/i18n/es-ES.json +++ b/module/config/i18n/es-ES.json @@ -238,15 +238,15 @@ "Name": { "name": "Nombre de la Mazmorra", "help": "Ajustes predeterminados de las mazmorras", - "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_Golden_Memories_Jarilo_VI": "Material: EXP de personaje (Flor de los recuerdos)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: EXP de personaje (Flor de los recuerdos)", + "Calyx_Golden_Memories_Penacony": "Material: EXP de personaje (Flor de los recuerdos)", + "Calyx_Golden_Aether_Jarilo_VI": "Material: EXP de conos de luz (Flor de éter)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: EXP de conos de luz (Flor de éter)", + "Calyx_Golden_Aether_Penacony": "Material: EXP de conos de luz (Flor de éter)", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Créditos (Flor de tesoros)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Créditos (Flor de tesoros)", + "Calyx_Golden_Treasures_Penacony": "Material: Créditos (Flor de tesoros)", "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)", @@ -266,14 +266,16 @@ "Stagnant_Shadow_Duty": "Ascension: Físico (Boothill / Robin / Yunli)", "Stagnant_Shadow_Blaze": "Ascension: Fuego (Himeko / Asta / Hook)", "Stagnant_Shadow_Scorch": "Ascension: Fuego (Guinaifen / Topaz y Conti)", - "Stagnant_Shadow_Ire": "Ascension: Fuego (Luciérnaga / Gallagher / Jiaoqiu)", + "Stagnant_Shadow_Ire": "Ascension: Fuego (Luciérnaga / Gallagher / Jiaoqiu / Lingsha)", "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 / Acheron)", + "Stagnant_Shadow_Mechwolf": "Ascension: Rayo (Moze)", "Stagnant_Shadow_Gust": "Ascension: Viento (Dan Heng / Bronya / Sampo)", "Stagnant_Shadow_Celestial": "Ascension: Viento (Blade / Huohuo / Cisne Negro)", + "Stagnant_Shadow_Gloam": "Ascension: Viento (Feixiao)", "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 (Jade / Sparkle)", @@ -293,15 +295,15 @@ "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", - "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_Golden_Memories_Jarilo_VI": "Material: EXP de personaje (Flor de los recuerdos)", + "Calyx_Golden_Memories_The_Xianzhou_Luofu": "Material: EXP de personaje (Flor de los recuerdos)", + "Calyx_Golden_Memories_Penacony": "Material: EXP de personaje (Flor de los recuerdos)", + "Calyx_Golden_Aether_Jarilo_VI": "Material: EXP de conos de luz (Flor de éter)", + "Calyx_Golden_Aether_The_Xianzhou_Luofu": "Material: EXP de conos de luz (Flor de éter)", + "Calyx_Golden_Aether_Penacony": "Material: EXP de conos de luz (Flor de éter)", + "Calyx_Golden_Treasures_Jarilo_VI": "Material: Créditos (Flor de tesoros)", + "Calyx_Golden_Treasures_The_Xianzhou_Luofu": "Material: Créditos (Flor de tesoros)", + "Calyx_Golden_Treasures_Penacony": "Material: Créditos (Flor de tesoros)", "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)", @@ -393,6 +395,7 @@ "DanHeng": "Dan Heng", "DanHengImbibitorLunae": "Dan Heng - Imbibitor Lunae", "DrRatio": "Dr. Ratio", + "Feixiao": "Feixiao", "Firefly": "Luciérnaga", "FuXuan": "Fu Xuan", "Gallagher": "Gallagher", @@ -414,6 +417,7 @@ "March7thPreservation": "Siete de Marzo: Conservación", "March7thTheHunt": "Siete de Marzo: Cacería", "Misha": "Misha", + "Moze": "Moze", "Natasha": "Natasha", "Pela": "Pela", "Qingque": "Qingque", @@ -567,13 +571,21 @@ "help": "" }, "Item_Raging_Heart": { - "name": "Ascension: Fuego (Luciérnaga / Gallagher / Jiaoqiu)", + "name": "Ascension: Fuego (Luciérnaga / Gallagher / Jiaoqiu / Lingsha)", "help": "" }, "Item_Dream_Fridge": { "name": "Ascension: Hielo (Misha)", "help": "" }, + "Item_Nail_of_the_Beast_Coffin": { + "name": "Ascension: Rayo (Moze)", + "help": "" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "name": "Ascension: Viento (Feixiao)", + "help": "" + }, "Item_Dream_Flamer": { "name": "Ascension: Cuántico (Jade / Sparkle)", "help": "" @@ -658,6 +670,10 @@ "name": "Tributo del sueño ceniciento (Colonipenal)", "help": "" }, + "Item_Auspice_Sliver": { + "name": "Campo de batalla de la bestia interior (El Luofu de Xianzhou)", + "help": "" + }, "Item_Squirming_Core": { "name": "Núcleo serpenteante", "help": "" @@ -703,7 +719,8 @@ "Echo_of_War_End_of_the_Eternal_Freeze": "El fin del Hielo Eterno (Jarilo-VI)", "Echo_of_War_Divine_Seed": "Semilla divina (El Luofu de Xianzhou)", "Echo_of_War_Borehole_Planet_Old_Crater": "Cráter del planeta devorado (Estación Espacial Herta)", - "Echo_of_War_Salutations_of_Ashen_Dreams": "Tributo del sueño ceniciento (Colonipenal)" + "Echo_of_War_Salutations_of_Ashen_Dreams": "Tributo del sueño ceniciento (Colonipenal)", + "Echo_of_War_Inner_Beast_Battlefield": "Campo de batalla de la bestia interior (El Luofu de Xianzhou)" }, "Team": { "name": "Equipo de mazmorra", @@ -1047,6 +1064,7 @@ "Dungeon": { "name": "Nombre de la Mazmorra", "help": "", + "Divergent_Universe_Famished_Worker": "Divergent_Universe_Famished_Worker (Obrero famélico)", "Divergent_Universe_Eternal_Comedy": " (Comedia eterna)", "Divergent_Universe_To_Sweet_Dreams": " (Hasta los dulces sueños)", "Divergent_Universe_Pouring_Blades": " (Lluvia de espadas)", diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index d95edbcc6..b1eace0fa 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -238,15 +238,15 @@ "Name": { "name": "Dungeon.Name.name", "help": "Dungeon.Name.help", - "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_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": "軌跡素材:存護(サポート部分)", @@ -266,42 +266,44 @@ "Stagnant_Shadow_Duty": "キャラクター昇格素材:物理(ブートヒル / ロビン / 雲璃)", "Stagnant_Shadow_Blaze": "キャラクター昇格素材:炎(姫子 / アスター / フック)", "Stagnant_Shadow_Scorch": "キャラクター昇格素材:炎(桂乃芬 / トパーズ&カブ)", - "Stagnant_Shadow_Ire": "キャラクター昇格素材:炎(ホタル / ギャラガー / 椒丘)", + "Stagnant_Shadow_Ire": "キャラクター昇格素材:炎(ホタル / ギャラガー / 椒丘 / 霊砂)", "Stagnant_Shadow_Rime": "キャラクター昇格素材:氷(三月なのか / ヘルタ / ジェパード / ペラ)", "Stagnant_Shadow_Icicle": "キャラクター昇格素材:氷(彦卿 / 鏡流 / ルアン・メェイ)", "Stagnant_Shadow_Nectar": "キャラクター昇格素材:氷(ミーシャ)", "Stagnant_Shadow_Fulmination": "キャラクター昇格素材:雷(アーラン / セーバル / 停雲 / 白露)", "Stagnant_Shadow_Doom": "キャラクター昇格素材:雷(カフカ / 景元 / 黄泉)", + "Stagnant_Shadow_Mechwolf": "キャラクター昇格素材:雷(モゼ)", "Stagnant_Shadow_Gust": "キャラクター昇格素材:風(丹恒 / ブローニャ / サンポ)", "Stagnant_Shadow_Celestial": "キャラクター昇格素材:風(刃 / フォフォ / ブラックスワン)", + "Stagnant_Shadow_Gloam": "キャラクター昇格素材:風(飛霄)", "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": "侵蝕トンネル・夢潜の路(侵蝕トンネル・夢潜の路)", - "Cavern_of_Corrosion_Path_of_Cavalier": "侵蝕トンネル・勇騎の路(侵蝕トンネル・勇騎の路)" + "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": "侵蝕トンネル・夢潜の路(夢潜の路)", + "Cavern_of_Corrosion_Path_of_Cavalier": "侵蝕トンネル・勇騎の路(勇騎の路)" }, "NameAtDoubleCalyx": { "name": "Dungeon.NameAtDoubleCalyx.name", "help": "Dungeon.NameAtDoubleCalyx.help", - "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_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": "軌跡素材:存護(サポート部分)", @@ -320,16 +322,16 @@ "NameAtDoubleRelic": { "name": "Dungeon.NameAtDoubleRelic.name", "help": "Dungeon.NameAtDoubleRelic.help", - "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": "侵蝕トンネル・夢潜の路(侵蝕トンネル・夢潜の路)", - "Cavern_of_Corrosion_Path_of_Cavalier": "侵蝕トンネル・勇騎の路(侵蝕トンネル・勇騎の路)" + "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": "侵蝕トンネル・夢潜の路(夢潜の路)", + "Cavern_of_Corrosion_Path_of_Cavalier": "侵蝕トンネル・勇騎の路(勇騎の路)" }, "Team": { "name": "Dungeon.Team.name", @@ -393,6 +395,7 @@ "DanHeng": "丹恒", "DanHengImbibitorLunae": "丹恒・飲月", "DrRatio": "Dr.レイシオ", + "Feixiao": "飛霄", "Firefly": "ホタル", "FuXuan": "符玄", "Gallagher": "ギャラガー", @@ -414,6 +417,7 @@ "March7thPreservation": "三月なのか・存護", "March7thTheHunt": "三月なのか・巡狩", "Misha": "ミーシャ", + "Moze": "モゼ", "Natasha": "ナターシャ", "Pela": "ペラ", "Qingque": "青雀", @@ -567,13 +571,21 @@ "help": "" }, "Item_Raging_Heart": { - "name": "キャラクター昇格素材:炎(ホタル / ギャラガー / 椒丘)", + "name": "キャラクター昇格素材:炎(ホタル / ギャラガー / 椒丘 / 霊砂)", "help": "" }, "Item_Dream_Fridge": { "name": "キャラクター昇格素材:氷(ミーシャ)", "help": "" }, + "Item_Nail_of_the_Beast_Coffin": { + "name": "キャラクター昇格素材:雷(モゼ)", + "help": "" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "name": "キャラクター昇格素材:風(飛霄)", + "help": "" + }, "Item_Dream_Flamer": { "name": "キャラクター昇格素材:量子(ジェイド / 花火)", "help": "" @@ -658,6 +670,10 @@ "name": "歴戦余韻・現世の夢の礼賛 (ピノコニー)", "help": "" }, + "Item_Auspice_Sliver": { + "name": "歴戦余韻・心獣の戦場 (仙舟「羅浮」)", + "help": "" + }, "Item_Squirming_Core": { "name": "脈動する原核", "help": "" @@ -703,7 +719,8 @@ "Echo_of_War_End_of_the_Eternal_Freeze": "歴戦余韻・寒波の幕切れ (ヤリーロ-VI)", "Echo_of_War_Divine_Seed": "歴戦余韻・不死の神実 (仙舟「羅浮」)", "Echo_of_War_Borehole_Planet_Old_Crater": "歴戦余韻・星を蝕む往日の面影 (宇宙ステーション「ヘルタ」)", - "Echo_of_War_Salutations_of_Ashen_Dreams": "歴戦余韻・現世の夢の礼賛 (ピノコニー)" + "Echo_of_War_Salutations_of_Ashen_Dreams": "歴戦余韻・現世の夢の礼賛 (ピノコニー)", + "Echo_of_War_Inner_Beast_Battlefield": "歴戦余韻・心獣の戦場 (仙舟「羅浮」)" }, "Team": { "name": "Weekly.Team.name", @@ -933,11 +950,11 @@ "World": { "name": "RogueWorld.World.name", "help": "RogueWorld.World.help", - "Simulated_Universe_World_3": "第三世界・模擬宇宙", - "Simulated_Universe_World_4": "第四世界・模擬宇宙", - "Simulated_Universe_World_5": "第五世界・模擬宇宙", - "Simulated_Universe_World_6": "第六世界・模擬宇宙", - "Simulated_Universe_World_8": "第八世界・模擬宇宙" + "Simulated_Universe_World_3": "第三世界", + "Simulated_Universe_World_4": "第四世界", + "Simulated_Universe_World_5": "第五世界", + "Simulated_Universe_World_6": "第六世界", + "Simulated_Universe_World_8": "第八世界" }, "Path": { "name": "RogueWorld.Path.name", @@ -1047,6 +1064,7 @@ "Dungeon": { "name": "Ornament.Dungeon.name", "help": "Ornament.Dungeon.help", + "Divergent_Universe_Famished_Worker": "Divergent_Universe_Famished_Worker(飢えた虫卒)", "Divergent_Universe_Eternal_Comedy": "(永遠の喜劇)", "Divergent_Universe_To_Sweet_Dreams": "(寄り添い眠る)", "Divergent_Universe_Pouring_Blades": "(剣の雨)", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index e52a9b40d..22ca2e3fc 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -238,15 +238,15 @@ "Name": { "name": "副本名称", "help": "默认打本设置", - "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_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": "行迹材料:存护(支援舱段)", @@ -266,42 +266,44 @@ "Stagnant_Shadow_Duty": "角色晋阶材料:物理(波提欧 / 知更鸟 / 云璃)", "Stagnant_Shadow_Blaze": "角色晋阶材料:火(姬子 / 艾丝妲 / 虎克)", "Stagnant_Shadow_Scorch": "角色晋阶材料:火(桂乃芬 / 托帕&账账)", - "Stagnant_Shadow_Ire": "角色晋阶材料:火(流萤 / 加拉赫 / 椒丘)", + "Stagnant_Shadow_Ire": "角色晋阶材料:火(流萤 / 加拉赫 / 椒丘 / 灵砂)", "Stagnant_Shadow_Rime": "角色晋阶材料:冰(三月七 / 黑塔 / 杰帕德 / 佩拉)", "Stagnant_Shadow_Icicle": "角色晋阶材料:冰(彦卿 / 镜流 / 阮•梅)", "Stagnant_Shadow_Nectar": "角色晋阶材料:冰(米沙)", "Stagnant_Shadow_Fulmination": "角色晋阶材料:雷(阿兰 / 希露瓦 / 停云 / 白露)", "Stagnant_Shadow_Doom": "角色晋阶材料:雷(卡芙卡 / 景元 / 黄泉)", + "Stagnant_Shadow_Mechwolf": "角色晋阶材料:雷(貊泽)", "Stagnant_Shadow_Gust": "角色晋阶材料:风(丹恒 / 布洛妮娅 / 桑博)", "Stagnant_Shadow_Celestial": "角色晋阶材料:风(刃 / 藿藿 / 黑天鹅)", + "Stagnant_Shadow_Gloam": "角色晋阶材料:风(飞霄)", "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": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Cavalier": "遗器:超击破套+终追套(勇骑之径•侵蚀隧洞)" + "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": "遗器:追击套+dot套(幽冥之径)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径)", + "Cavern_of_Corrosion_Path_of_Cavalier": "遗器:超击破套+终追套(勇骑之径)" }, "NameAtDoubleCalyx": { "name": "有双倍花活动时,选择副本", "help": "次数耗尽后回退到默认打本设置", - "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_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": "行迹材料:存护(支援舱段)", @@ -320,16 +322,16 @@ "NameAtDoubleRelic": { "name": "有遗器活动时,选择副本", "help": "次数耗尽后回退到默认打本设置", - "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": "遗器:追击套+dot套(幽冥之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径•侵蚀隧洞)", - "Cavern_of_Corrosion_Path_of_Cavalier": "遗器:超击破套+终追套(勇骑之径•侵蚀隧洞)" + "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": "遗器:追击套+dot套(幽冥之径)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遗器:负面套+击破套(梦潜之径)", + "Cavern_of_Corrosion_Path_of_Cavalier": "遗器:超击破套+终追套(勇骑之径)" }, "Team": { "name": "打本队伍", @@ -393,6 +395,7 @@ "DanHeng": "丹恒", "DanHengImbibitorLunae": "丹恒•饮月", "DrRatio": "真理医生", + "Feixiao": "飞霄", "Firefly": "流萤", "FuXuan": "符玄", "Gallagher": "加拉赫", @@ -414,6 +417,7 @@ "March7thPreservation": "三月七•存护", "March7thTheHunt": "三月七•巡猎", "Misha": "米沙", + "Moze": "貊泽", "Natasha": "娜塔莎", "Pela": "佩拉", "Qingque": "青雀", @@ -567,13 +571,21 @@ "help": "" }, "Item_Raging_Heart": { - "name": "角色晋阶材料:火(流萤 / 加拉赫 / 椒丘)", + "name": "角色晋阶材料:火(流萤 / 加拉赫 / 椒丘 / 灵砂)", "help": "" }, "Item_Dream_Fridge": { "name": "角色晋阶材料:冰(米沙)", "help": "" }, + "Item_Nail_of_the_Beast_Coffin": { + "name": "角色晋阶材料:雷(貊泽)", + "help": "" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "name": "角色晋阶材料:风(飞霄)", + "help": "" + }, "Item_Dream_Flamer": { "name": "角色晋阶材料:量子(翡翠 / 花火)", "help": "" @@ -658,6 +670,10 @@ "name": "尘梦的赞礼•历战余响 (匹诺康尼)", "help": "" }, + "Item_Auspice_Sliver": { + "name": "心兽的战场•历战余响 (仙舟「罗浮」)", + "help": "" + }, "Item_Squirming_Core": { "name": "蠢动原核", "help": "" @@ -703,7 +719,8 @@ "Echo_of_War_End_of_the_Eternal_Freeze": "寒潮的落幕•历战余响 (雅利洛-Ⅵ)", "Echo_of_War_Divine_Seed": "不死的神实•历战余响 (仙舟「罗浮」)", "Echo_of_War_Borehole_Planet_Old_Crater": "蛀星的旧靥•历战余响 (空间站「黑塔」)", - "Echo_of_War_Salutations_of_Ashen_Dreams": "尘梦的赞礼•历战余响 (匹诺康尼)" + "Echo_of_War_Salutations_of_Ashen_Dreams": "尘梦的赞礼•历战余响 (匹诺康尼)", + "Echo_of_War_Inner_Beast_Battlefield": "心兽的战场•历战余响 (仙舟「罗浮」)" }, "Team": { "name": "打本队伍", @@ -933,11 +950,11 @@ "World": { "name": "模拟宇宙关卡", "help": "", - "Simulated_Universe_World_3": "第三世界•模拟宇宙", - "Simulated_Universe_World_4": "第四世界•模拟宇宙", - "Simulated_Universe_World_5": "第五世界•模拟宇宙", - "Simulated_Universe_World_6": "第六世界•模拟宇宙", - "Simulated_Universe_World_8": "第八世界•模拟宇宙" + "Simulated_Universe_World_3": "第三世界", + "Simulated_Universe_World_4": "第四世界", + "Simulated_Universe_World_5": "第五世界", + "Simulated_Universe_World_6": "第六世界", + "Simulated_Universe_World_8": "第八世界" }, "Path": { "name": "命途", @@ -1047,6 +1064,7 @@ "Dungeon": { "name": "副本名称", "help": "", + "Divergent_Universe_Famished_Worker": "Divergent_Universe_Famished_Worker(蠹役饥肠)", "Divergent_Universe_Eternal_Comedy": "奔狼+火宫(永恒笑剧)", "Divergent_Universe_To_Sweet_Dreams": "茨冈尼亚+出云神国(伴你入眠)", "Divergent_Universe_Pouring_Blades": "苍穹+匹诺康尼(天剑如雨)", diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 3965da095..63215d961 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -238,15 +238,15 @@ "Name": { "name": "副本名稱", "help": "默認打本設定", - "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_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": "行跡材料:存護(支援艙段)", @@ -266,42 +266,44 @@ "Stagnant_Shadow_Duty": "角色晉階材料:物理(波提歐 / 知更鳥 / 雲璃)", "Stagnant_Shadow_Blaze": "角色晉階材料:火(姬子 / 艾絲妲 / 虎克)", "Stagnant_Shadow_Scorch": "角色晉階材料:火(桂乃芬 / 托帕&帳帳)", - "Stagnant_Shadow_Ire": "角色晉階材料:火(流螢 / 加拉赫 / 椒丘)", + "Stagnant_Shadow_Ire": "角色晉階材料:火(流螢 / 加拉赫 / 椒丘 / 靈砂)", "Stagnant_Shadow_Rime": "角色晉階材料:冰(三月七 / 黑塔 / 傑帕德 / 佩拉)", "Stagnant_Shadow_Icicle": "角色晉階材料:冰(彥卿 / 鏡流 / 阮•梅)", "Stagnant_Shadow_Nectar": "角色晉階材料:冰(米沙)", "Stagnant_Shadow_Fulmination": "角色晉階材料:雷(阿蘭 / 希露瓦 / 停雲 / 白露)", "Stagnant_Shadow_Doom": "角色晉階材料:雷(卡芙卡 / 景元 / 黃泉)", + "Stagnant_Shadow_Mechwolf": "角色晉階材料:雷(貊澤)", "Stagnant_Shadow_Gust": "角色晉階材料:風(丹恆 / 布洛妮婭 / 桑博)", "Stagnant_Shadow_Celestial": "角色晉階材料:風(刃 / 藿藿 / 黑天鵝)", + "Stagnant_Shadow_Gloam": "角色晉階材料:風(飛霄)", "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": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套(夢潛之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Cavalier": "遺器:超擊破套+終追套(勇騎之徑•侵蝕隧洞)" + "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": "遺器:追擊套+dot套(幽冥之徑)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套((夢潛之徑)", + "Cavern_of_Corrosion_Path_of_Cavalier": "遺器:超擊破套+終追套(勇騎之徑)" }, "NameAtDoubleCalyx": { "name": "有雙倍花活動時,選擇副本", "help": "次數耗儘後回退到默認打本設定", - "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_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": "行跡材料:存護(支援艙段)", @@ -320,16 +322,16 @@ "NameAtDoubleRelic": { "name": "有遺器活動時,選擇副本", "help": "次數耗儘後回退到默認打本設定", - "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": "遺器:追擊套+dot套(幽冥之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套(夢潛之徑•侵蝕隧洞)", - "Cavern_of_Corrosion_Path_of_Cavalier": "遺器:超擊破套+終追套(勇騎之徑•侵蝕隧洞)" + "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": "遺器:追擊套+dot套(幽冥之徑)", + "Cavern_of_Corrosion_Path_of_Dreamdive": "遺器:負面套+擊破套((夢潛之徑)", + "Cavern_of_Corrosion_Path_of_Cavalier": "遺器:超擊破套+終追套(勇騎之徑)" }, "Team": { "name": "打本隊伍", @@ -393,6 +395,7 @@ "DanHeng": "丹恆", "DanHengImbibitorLunae": "丹恆•飲月", "DrRatio": "真理醫生", + "Feixiao": "飛霄", "Firefly": "流螢", "FuXuan": "符玄", "Gallagher": "加拉赫", @@ -414,6 +417,7 @@ "March7thPreservation": "三月七•存護", "March7thTheHunt": "三月七•巡獵", "Misha": "米沙", + "Moze": "貊澤", "Natasha": "娜塔莎", "Pela": "佩拉", "Qingque": "青雀", @@ -567,13 +571,21 @@ "help": "" }, "Item_Raging_Heart": { - "name": "角色晉階材料:火(流螢 / 加拉赫 / 椒丘)", + "name": "角色晉階材料:火(流螢 / 加拉赫 / 椒丘 / 靈砂)", "help": "" }, "Item_Dream_Fridge": { "name": "角色晉階材料:冰(米沙)", "help": "" }, + "Item_Nail_of_the_Beast_Coffin": { + "name": "角色晉階材料:雷(貊澤)", + "help": "" + }, + "Item_A_Glass_of_the_Besotted_Era": { + "name": "角色晉階材料:風(飛霄)", + "help": "" + }, "Item_Dream_Flamer": { "name": "角色晉階材料:量子(翡翠 / 花火)", "help": "" @@ -658,6 +670,10 @@ "name": "塵夢的讚禮•歷戰餘響 (匹諾康尼)", "help": "" }, + "Item_Auspice_Sliver": { + "name": "心獸的戰場•歷戰餘響 (仙舟「羅浮」)", + "help": "" + }, "Item_Squirming_Core": { "name": "蠢動原核", "help": "" @@ -703,7 +719,8 @@ "Echo_of_War_End_of_the_Eternal_Freeze": "寒潮的落幕•歷戰餘響 (雅利洛-Ⅵ)", "Echo_of_War_Divine_Seed": "不死的神實•歷戰餘響 (仙舟「羅浮」)", "Echo_of_War_Borehole_Planet_Old_Crater": "蛀星的舊靨•歷戰餘響 (太空站「黑塔」)", - "Echo_of_War_Salutations_of_Ashen_Dreams": "塵夢的讚禮•歷戰餘響 (匹諾康尼)" + "Echo_of_War_Salutations_of_Ashen_Dreams": "塵夢的讚禮•歷戰餘響 (匹諾康尼)", + "Echo_of_War_Inner_Beast_Battlefield": "心獸的戰場•歷戰餘響 (仙舟「羅浮」)" }, "Team": { "name": "打本隊伍", @@ -933,11 +950,11 @@ "World": { "name": "模拟宇宙关卡", "help": "", - "Simulated_Universe_World_3": "第三世界•模擬宇宙", - "Simulated_Universe_World_4": "第四世界•模擬宇宙", - "Simulated_Universe_World_5": "第五世界•模擬宇宙", - "Simulated_Universe_World_6": "第六世界•模擬宇宙", - "Simulated_Universe_World_8": "第八世界•模擬宇宙" + "Simulated_Universe_World_3": "第三世界", + "Simulated_Universe_World_4": "第四世界", + "Simulated_Universe_World_5": "第五世界", + "Simulated_Universe_World_6": "第六世界", + "Simulated_Universe_World_8": "第八世界" }, "Path": { "name": "命途", @@ -1047,6 +1064,7 @@ "Dungeon": { "name": "副本名稱", "help": "", + "Divergent_Universe_Famished_Worker": "Divergent_Universe_Famished_Worker(蠹役飢腸)", "Divergent_Universe_Eternal_Comedy": "奔狼+火宮(永恆笑劇)", "Divergent_Universe_To_Sweet_Dreams": "茨岡尼亞+出雲神國(伴你入眠)", "Divergent_Universe_Pouring_Blades": "天空+匹諾康尼(天劍如雨)", diff --git a/module/config/stored/stored_generated.py b/module/config/stored/stored_generated.py index 7a4c52f93..47900dae0 100644 --- a/module/config/stored/stored_generated.py +++ b/module/config/stored/stored_generated.py @@ -56,6 +56,8 @@ class StoredGenerated: Item_IPC_Work_Permit = StoredPlanner("Dungeon.Planner.Item_IPC_Work_Permit") Item_Raging_Heart = StoredPlanner("Dungeon.Planner.Item_Raging_Heart") Item_Dream_Fridge = StoredPlanner("Dungeon.Planner.Item_Dream_Fridge") + Item_Nail_of_the_Beast_Coffin = StoredPlanner("Dungeon.Planner.Item_Nail_of_the_Beast_Coffin") + Item_A_Glass_of_the_Besotted_Era = StoredPlanner("Dungeon.Planner.Item_A_Glass_of_the_Besotted_Era") Item_Dream_Flamer = StoredPlanner("Dungeon.Planner.Item_Dream_Flamer") Item_Worldbreaker_Blade = StoredPlanner("Dungeon.Planner.Item_Worldbreaker_Blade") Item_Arrow_of_the_Starchaser = StoredPlanner("Dungeon.Planner.Item_Arrow_of_the_Starchaser") @@ -77,6 +79,7 @@ class StoredGenerated: Item_Regret_of_Infinite_Ochema = StoredPlanner("Dungeon.Planner.Item_Regret_of_Infinite_Ochema") Item_Past_Evils_of_the_Borehole_Planet_Disaster = StoredPlanner("Dungeon.Planner.Item_Past_Evils_of_the_Borehole_Planet_Disaster") Item_Lost_Echo_of_the_Shared_Wish = StoredPlanner("Dungeon.Planner.Item_Lost_Echo_of_the_Shared_Wish") + Item_Auspice_Sliver = StoredPlanner("Dungeon.Planner.Item_Auspice_Sliver") Item_Squirming_Core = StoredPlanner("Dungeon.Planner.Item_Squirming_Core") Item_Conqueror_Will = StoredPlanner("Dungeon.Planner.Item_Conqueror_Will") Item_Silvermane_Medal = StoredPlanner("Dungeon.Planner.Item_Silvermane_Medal") diff --git a/module/config/utils.py b/module/config/utils.py index af05bb18d..cb61a028b 100644 --- a/module/config/utils.py +++ b/module/config/utils.py @@ -2,6 +2,7 @@ import json import os import random import string +from collections import deque from datetime import datetime, timedelta, timezone import yaml @@ -190,57 +191,95 @@ def alas_instance(): def deep_get(d, keys, default=None): - """ - Get values in dictionary safely. - https://stackoverflow.com/questions/25833613/safe-method-to-get-value-of-nested-dictionary - - Args: - d (dict): - keys (str, list): Such as `Scheduler.NextRun.value` - default: Default return if key not found. - - Returns: - - """ - if isinstance(keys, str): + # 240 + 30 * depth (ns) + if type(keys) is str: keys = keys.split('.') - assert type(keys) is list - if d is None: - return default - if not keys: + + try: + for k in keys: + d = d[k] return d - return deep_get(d.get(keys[0]), keys[1:], default) + # No such key + except KeyError: + return default + # Input `keys` is not iterable or input `d` is not dict + except TypeError: + return default def deep_set(d, keys, value): """ Set value into dictionary safely, imitating deep_get(). """ - if isinstance(keys, str): + # 150 * depth (ns) + if type(keys) is str: keys = keys.split('.') - assert type(keys) is list - if not keys: - return value - if not isinstance(d, dict): - d = {} - d[keys[0]] = deep_set(d.get(keys[0], {}), keys[1:], value) - return d + + first = True + exist = True + prev_d = None + prev_k = None + prev_k2 = None + try: + for k in keys: + if first: + prev_d = d + prev_k = k + first = False + continue + try: + # if key in dict: dict[key] > dict.get > dict.setdefault > try dict[key] except + if exist and prev_k in d: + prev_d = d + d = d[prev_k] + else: + exist = False + new = {} + d[prev_k] = new + d = new + except TypeError: + # `d` is not dict + exist = False + d = {} + prev_d[prev_k2] = {prev_k: d} + + prev_k2 = prev_k + prev_k = k + # prev_k2, prev_k = prev_k, k + # Input `keys` is not iterable + except TypeError: + return + + # Last key, set value + try: + d[prev_k] = value + return + # Last value `d` is not dict + except TypeError: + prev_d[prev_k2] = {prev_k: value} + return def deep_pop(d, keys, default=None): - """ - Pop value from dictionary safely, imitating deep_get(). - """ - if isinstance(keys, str): + if type(keys) is str: keys = keys.split('.') - assert type(keys) is list - if not isinstance(d, dict): + + try: + for k in keys[:-1]: + d = d[k] + return d.pop(keys[-1], default) + # No such key + except KeyError: return default - if not keys: + # Input `keys` is not iterable or input `d` is not dict + except TypeError: + return default + # Input `keys` out of index + except IndexError: + return default + # Last `d` is not dict + except AttributeError: return default - elif len(keys) == 1: - return d.pop(keys[0], default) - return deep_pop(d.get(keys[0]), keys[1:], default) def deep_default(d, keys, value): @@ -262,26 +301,75 @@ def deep_default(d, keys, value): return d -def deep_iter(data, depth=0, current_depth=1): +def deep_iter(data, min_depth=None, depth=3): """ - Iter a dictionary safely. + 300us on alas.json depth=3 (530+ rows) Args: - data (dict): - depth (int): Maximum depth to iter - current_depth (int): + data: + min_depth: + depth: Returns: - list: Key path - Any: + """ - if isinstance(data, dict) \ - and (depth and current_depth <= depth): - for key, value in data.items(): - for child_path, child_value in deep_iter(value, depth=depth, current_depth=current_depth + 1): - yield [key] + child_path, child_value - else: - yield [], data + if min_depth is None: + min_depth = depth + assert 1 <= min_depth <= depth + + # Equivalent to dict.items() + try: + if depth == 1: + for k, v in data.items(): + yield [k], v + return + # Iter first depth + elif min_depth == 1: + q = deque() + for k, v in data.items(): + key = [k] + if type(v) is dict: + q.append((key, v)) + else: + yield key, v + # Iter target depth only + else: + q = deque() + for k, v in data.items(): + key = [k] + if type(v) is dict: + q.append((key, v)) + except AttributeError: + # `data` is not dict + return + + # Iter depths + current = 2 + while current <= depth: + new_q = deque() + # max depth + if current == depth: + for key, data in q: + for k, v in data.items(): + yield key + [k], v + # in target depth + elif min_depth <= current < depth: + for key, data in q: + for k, v in data.items(): + subkey = key + [k] + if type(v) is dict: + new_q.append((subkey, v)) + else: + yield subkey, v + # Haven't reached min depth + else: + for key, data in q: + for k, v in data.items(): + subkey = key + [k] + if type(v) is dict: + new_q.append((subkey, v)) + q = new_q + current += 1 def parse_value(value, data): diff --git a/module/device/connection.py b/module/device/connection.py index 59c64e9b4..bd88548e4 100644 --- a/module/device/connection.py +++ b/module/device/connection.py @@ -721,7 +721,12 @@ class Connection(ConnectionAttr): serial_list (list[str]): """ import asyncio + from concurrent.futures import ThreadPoolExecutor ev = asyncio.new_event_loop() + pool = ThreadPoolExecutor( + max_workers=len(serial_list), + thread_name_prefix='adb_brute_force_connect', + ) def _connect(serial): msg = self.adb_client.connect(serial) @@ -729,10 +734,12 @@ class Connection(ConnectionAttr): return msg async def connect(): - tasks = [ev.run_in_executor(None, _connect, serial) for serial in serial_list] + tasks = [ev.run_in_executor(pool, _connect, serial) for serial in serial_list] await asyncio.gather(*tasks) ev.run_until_complete(connect()) + pool.shutdown(wait=False) + ev.close() @Config.when(DEVICE_OVER_HTTP=True) def adb_connect(self): diff --git a/module/device/method/nemu_ipc.py b/module/device/method/nemu_ipc.py index cdb159f48..0fde50d51 100644 --- a/module/device/method/nemu_ipc.py +++ b/module/device/method/nemu_ipc.py @@ -275,11 +275,25 @@ class NemuIpcImpl: def __exit__(self, exc_type, exc_val, exc_tb): self.disconnect() + if has_cached_property(self, '_ev'): + self._ev.close() + del_cached_property(self, '_ev') + if has_cached_property(self, '_pool'): + self._pool.shutdown(wait=False) + del_cached_property(self, '_pool') @cached_property def _ev(self): return asyncio.new_event_loop() + @cached_property + def _pool(self): + from concurrent.futures import ThreadPoolExecutor + return ThreadPoolExecutor( + max_workers=1, + thread_name_prefix='NemuIpc', + ) + async def ev_run_async(self, func, *args, timeout=0.15, **kwargs): """ Args: @@ -294,7 +308,7 @@ class NemuIpcImpl: func_wrapped = partial(func, *args, **kwargs) # Increased timeout for slow PCs # Default screenshot interval is 0.2s, so a 0.15s timeout would have a fast retry without extra time costs - result = await asyncio.wait_for(self._ev.run_in_executor(None, func_wrapped), timeout=timeout) + result = await asyncio.wait_for(self._ev.run_in_executor(self._pool, func_wrapped), timeout=timeout) return result def ev_run_sync(self, func, *args, **kwargs): diff --git a/tasks/character/keywords/character_list.py b/tasks/character/keywords/character_list.py index 269c219dd..84793a534 100644 --- a/tasks/character/keywords/character_list.py +++ b/tasks/character/keywords/character_list.py @@ -129,8 +129,17 @@ DrRatio = CharacterList( jp='Dr.レイシオ', es='Dr. Ratio', ) -Firefly = CharacterList( +Feixiao = CharacterList( id=15, + name='Feixiao', + cn='飞霄', + cht='飛霄', + en='Feixiao', + jp='飛霄', + es='Feixiao', +) +Firefly = CharacterList( + id=16, name='Firefly', cn='流萤', cht='流螢', @@ -139,7 +148,7 @@ Firefly = CharacterList( es='Luciérnaga', ) FuXuan = CharacterList( - id=16, + id=17, name='FuXuan', cn='符玄', cht='符玄', @@ -148,7 +157,7 @@ FuXuan = CharacterList( es='Fu Xuan', ) Gallagher = CharacterList( - id=17, + id=18, name='Gallagher', cn='加拉赫', cht='加拉赫', @@ -157,7 +166,7 @@ Gallagher = CharacterList( es='Gallagher', ) Gepard = CharacterList( - id=18, + id=19, name='Gepard', cn='杰帕德', cht='傑帕德', @@ -166,7 +175,7 @@ Gepard = CharacterList( es='Gepard', ) Guinaifen = CharacterList( - id=19, + id=20, name='Guinaifen', cn='桂乃芬', cht='桂乃芬', @@ -175,7 +184,7 @@ Guinaifen = CharacterList( es='Guinaifen', ) Hanya = CharacterList( - id=20, + id=21, name='Hanya', cn='寒鸦', cht='寒鴉', @@ -184,7 +193,7 @@ Hanya = CharacterList( es='Hanya', ) Herta = CharacterList( - id=21, + id=22, name='Herta', cn='黑塔', cht='黑塔', @@ -193,7 +202,7 @@ Herta = CharacterList( es='Herta', ) Himeko = CharacterList( - id=22, + id=23, name='Himeko', cn='姬子', cht='姬子', @@ -202,7 +211,7 @@ Himeko = CharacterList( es='Himeko', ) Hook = CharacterList( - id=23, + id=24, name='Hook', cn='虎克', cht='虎克', @@ -211,7 +220,7 @@ Hook = CharacterList( es='Hook', ) Huohuo = CharacterList( - id=24, + id=25, name='Huohuo', cn='藿藿', cht='藿藿', @@ -220,7 +229,7 @@ Huohuo = CharacterList( es='Huohuo', ) Jade = CharacterList( - id=25, + id=26, name='Jade', cn='翡翠', cht='翡翠', @@ -229,7 +238,7 @@ Jade = CharacterList( es='Jade', ) Jiaoqiu = CharacterList( - id=26, + id=27, name='Jiaoqiu', cn='椒丘', cht='椒丘', @@ -238,7 +247,7 @@ Jiaoqiu = CharacterList( es='Jiaoqiu', ) JingYuan = CharacterList( - id=27, + id=28, name='JingYuan', cn='景元', cht='景元', @@ -247,7 +256,7 @@ JingYuan = CharacterList( es='Jing Yuan', ) Jingliu = CharacterList( - id=28, + id=29, name='Jingliu', cn='镜流', cht='鏡流', @@ -256,7 +265,7 @@ Jingliu = CharacterList( es='Jingliu', ) Kafka = CharacterList( - id=29, + id=30, name='Kafka', cn='卡芙卡', cht='卡芙卡', @@ -264,8 +273,17 @@ Kafka = CharacterList( jp='カフカ', es='Kafka', ) +Lingsha = CharacterList( + id=31, + name='Lingsha', + cn='灵砂', + cht='靈砂', + en='Lingsha', + jp='霊砂', + es='Lingsha', +) Luka = CharacterList( - id=30, + id=32, name='Luka', cn='卢卡', cht='盧卡', @@ -274,7 +292,7 @@ Luka = CharacterList( es='Luka', ) Luocha = CharacterList( - id=31, + id=33, name='Luocha', cn='罗刹', cht='羅剎', @@ -283,7 +301,7 @@ Luocha = CharacterList( es='Luocha', ) Lynx = CharacterList( - id=32, + id=34, name='Lynx', cn='玲可', cht='玲可', @@ -292,7 +310,7 @@ Lynx = CharacterList( es='Lynx', ) March7thPreservation = CharacterList( - id=33, + id=35, name='March7thPreservation', cn='三月七•存护', cht='三月七•存護', @@ -301,7 +319,7 @@ March7thPreservation = CharacterList( es='Siete de Marzo: Conservación', ) March7thTheHunt = CharacterList( - id=34, + id=36, name='March7thTheHunt', cn='三月七•巡猎', cht='三月七•巡獵', @@ -310,7 +328,7 @@ March7thTheHunt = CharacterList( es='Siete de Marzo: Cacería', ) Misha = CharacterList( - id=35, + id=37, name='Misha', cn='米沙', cht='米沙', @@ -318,8 +336,17 @@ Misha = CharacterList( jp='ミーシャ', es='Misha', ) +Moze = CharacterList( + id=38, + name='Moze', + cn='貊泽', + cht='貊澤', + en='Moze', + jp='モゼ', + es='Moze', +) Natasha = CharacterList( - id=36, + id=39, name='Natasha', cn='娜塔莎', cht='娜塔莎', @@ -328,7 +355,7 @@ Natasha = CharacterList( es='Natasha', ) Pela = CharacterList( - id=37, + id=40, name='Pela', cn='佩拉', cht='佩拉', @@ -337,7 +364,7 @@ Pela = CharacterList( es='Pela', ) Qingque = CharacterList( - id=38, + id=41, name='Qingque', cn='青雀', cht='青雀', @@ -346,7 +373,7 @@ Qingque = CharacterList( es='Qingque', ) Robin = CharacterList( - id=39, + id=42, name='Robin', cn='知更鸟', cht='知更鳥', @@ -355,7 +382,7 @@ Robin = CharacterList( es='Robin', ) RuanMei = CharacterList( - id=40, + id=43, name='RuanMei', cn='阮•梅', cht='阮•梅', @@ -364,7 +391,7 @@ RuanMei = CharacterList( es='Ruan Mei', ) Sampo = CharacterList( - id=41, + id=44, name='Sampo', cn='桑博', cht='桑博', @@ -373,7 +400,7 @@ Sampo = CharacterList( es='Sampo', ) Seele = CharacterList( - id=42, + id=45, name='Seele', cn='希儿', cht='希兒', @@ -382,7 +409,7 @@ Seele = CharacterList( es='Seele', ) Serval = CharacterList( - id=43, + id=46, name='Serval', cn='希露瓦', cht='希露瓦', @@ -391,7 +418,7 @@ Serval = CharacterList( es='Serval', ) SilverWolf = CharacterList( - id=44, + id=47, name='SilverWolf', cn='银狼', cht='銀狼', @@ -400,7 +427,7 @@ SilverWolf = CharacterList( es='Silver Wolf', ) Sparkle = CharacterList( - id=45, + id=48, name='Sparkle', cn='花火', cht='花火', @@ -409,7 +436,7 @@ Sparkle = CharacterList( es='Sparkle', ) Sushang = CharacterList( - id=46, + id=49, name='Sushang', cn='素裳', cht='素裳', @@ -418,7 +445,7 @@ Sushang = CharacterList( es='Sushang', ) Tingyun = CharacterList( - id=47, + id=50, name='Tingyun', cn='停云', cht='停雲', @@ -427,7 +454,7 @@ Tingyun = CharacterList( es='Tingyun', ) TopazNumby = CharacterList( - id=48, + id=51, name='TopazNumby', cn='托帕&账账', cht='托帕&帳帳', @@ -436,7 +463,7 @@ TopazNumby = CharacterList( es='Topaz y Conti', ) TrailblazerDestruction = CharacterList( - id=49, + id=52, name='TrailblazerDestruction', cn='Trailblazer•毁灭', cht='Trailblazer•毀滅', @@ -445,7 +472,7 @@ TrailblazerDestruction = CharacterList( es='Trailblazer: Destrucción', ) TrailblazerHarmony = CharacterList( - id=50, + id=53, name='TrailblazerHarmony', cn='Trailblazer•同谐', cht='Trailblazer•同諧', @@ -454,7 +481,7 @@ TrailblazerHarmony = CharacterList( es='Trailblazer: Armonía', ) TrailblazerPreservation = CharacterList( - id=51, + id=54, name='TrailblazerPreservation', cn='Trailblazer•存护', cht='Trailblazer•存護', @@ -463,7 +490,7 @@ TrailblazerPreservation = CharacterList( es='Trailblazer: Conservación', ) Welt = CharacterList( - id=52, + id=55, name='Welt', cn='瓦尔特', cht='瓦爾特', @@ -472,7 +499,7 @@ Welt = CharacterList( es='Welt', ) Xueyi = CharacterList( - id=53, + id=56, name='Xueyi', cn='雪衣', cht='雪衣', @@ -481,7 +508,7 @@ Xueyi = CharacterList( es='Xueyi', ) Yanqing = CharacterList( - id=54, + id=57, name='Yanqing', cn='彦卿', cht='彥卿', @@ -490,7 +517,7 @@ Yanqing = CharacterList( es='Yanqing', ) Yukong = CharacterList( - id=55, + id=58, name='Yukong', cn='驭空', cht='馭空', @@ -499,7 +526,7 @@ Yukong = CharacterList( es='Yukong', ) Yunli = CharacterList( - id=56, + id=59, name='Yunli', cn='云璃', cht='雲璃', diff --git a/tasks/combat/combat.py b/tasks/combat/combat.py index 55728654f..ad8e9d611 100644 --- a/tasks/combat/combat.py +++ b/tasks/combat/combat.py @@ -324,6 +324,9 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo if self.is_in_main(): logger.info('Combat finishes at page_main') return True + if self.appear(COMBAT_PREPARE): + logger.info('Combat finishes at COMBAT_PREPARE') + return True if self.is_combat_executing(): logger.info('Combat finishes at another combat') return False @@ -427,6 +430,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo if self._combat_should_reenter(): continue if finish: + self.combat_exit() break # Reset combat_wave_cost, so handle_combat_interact() won't activate before handle_combat_prepare() self.combat_wave_cost = 10 diff --git a/tasks/daily/daily_quest.py b/tasks/daily/daily_quest.py index a5d7a9d7b..d60d2ad5a 100644 --- a/tasks/daily/daily_quest.py +++ b/tasks/daily/daily_quest.py @@ -21,7 +21,7 @@ from tasks.daily.synthesize import SynthesizeMaterialUI from tasks.daily.use_technique import UseTechniqueUI from tasks.dungeon.assets.assets_dungeon_ui import DAILY_TRAINING_CHECK from tasks.dungeon.keywords import KEYWORDS_DUNGEON_TAB -from tasks.dungeon.ui import DungeonUI +from tasks.dungeon.ui.ui import DungeonUI from tasks.item.consumable_usage import ConsumableUsageUI from tasks.item.relics import RelicsUI from tasks.map.route.loader import RouteLoader diff --git a/tasks/dungeon/assets/assets_dungeon_ui.py b/tasks/dungeon/assets/assets_dungeon_ui.py index ba77ca705..ba4730031 100644 --- a/tasks/dungeon/assets/assets_dungeon_ui.py +++ b/tasks/dungeon/assets/assets_dungeon_ui.py @@ -3,36 +3,6 @@ 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( @@ -73,16 +43,6 @@ LIST_LOADED_CHECK = ButtonWrapper( button=(576, 606, 951, 664), ), ) -OCR_DUNGEON_LIST = ButtonWrapper( - name='OCR_DUNGEON_LIST', - share=Button( - file='./assets/share/dungeon/ui/OCR_DUNGEON_LIST.png', - area=(581, 176, 1165, 661), - search=(561, 156, 1185, 681), - color=(212, 214, 220), - button=(440, 176, 588, 656), - ), -) OCR_DUNGEON_NAV = ButtonWrapper( name='OCR_DUNGEON_NAV', share=Button( diff --git a/tasks/dungeon/assets/assets_dungeon_ui_list.py b/tasks/dungeon/assets/assets_dungeon_ui_list.py new file mode 100644 index 000000000..275e63cb8 --- /dev/null +++ b/tasks/dungeon/assets/assets_dungeon_ui_list.py @@ -0,0 +1,65 @@ +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 ``` + +LIST_ASCENDING = ButtonWrapper( + name='LIST_ASCENDING', + share=Button( + file='./assets/share/dungeon/ui_list/LIST_ASCENDING.png', + area=(1125, 643, 1143, 661), + search=(1105, 623, 1163, 681), + color=(195, 194, 196), + button=(1125, 643, 1143, 661), + ), +) +LIST_DESCENDING = ButtonWrapper( + name='LIST_DESCENDING', + share=Button( + file='./assets/share/dungeon/ui_list/LIST_DESCENDING.png', + area=(1125, 643, 1143, 661), + search=(1105, 623, 1163, 681), + color=(195, 194, 196), + button=(1125, 643, 1143, 661), + ), +) +OCR_DUNGEON_LIST = ButtonWrapper( + name='OCR_DUNGEON_LIST', + share=Button( + file='./assets/share/dungeon/ui_list/OCR_DUNGEON_LIST.png', + area=(581, 176, 1165, 661), + search=(561, 156, 1185, 681), + color=(212, 214, 220), + button=(440, 176, 588, 656), + ), +) +OCR_DUNGEON_NAME = ButtonWrapper( + name='OCR_DUNGEON_NAME', + share=Button( + file='./assets/share/dungeon/ui_list/OCR_DUNGEON_NAME.png', + area=(563, 172, 788, 624), + search=(543, 152, 808, 644), + color=(245, 243, 245), + button=(563, 172, 788, 624), + ), +) +OCR_DUNGEON_NAME_ROGUE = ButtonWrapper( + name='OCR_DUNGEON_NAME_ROGUE', + share=Button( + file='./assets/share/dungeon/ui_list/OCR_DUNGEON_NAME_ROGUE.png', + area=(563, 292, 788, 624), + search=(543, 272, 808, 644), + color=(249, 247, 249), + button=(563, 292, 788, 624), + ), +) +OCR_DUNGEON_TELEPORT = ButtonWrapper( + name='OCR_DUNGEON_TELEPORT', + share=Button( + file='./assets/share/dungeon/ui_list/OCR_DUNGEON_TELEPORT.png', + area=(1013, 172, 1163, 624), + search=(993, 152, 1183, 644), + color=(231, 234, 230), + button=(1013, 172, 1163, 624), + ), +) diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index c628cd15e..0da8d343b 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -213,7 +213,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): elif require and not self.support_once: # Run with support all the way return self._dungeon_run(dungeon=dungeon, team=team, wave_limit=0, - support_character=self.config.DungeonSupport_Character) + support_character=self.config.DungeonSupport_Character) else: # Normal run @@ -250,10 +250,10 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if self.has_double_rogue_event(): rogue = self.get_double_rogue_remain() if self.has_double_calyx_event(): - self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Calyx_Golden) + 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_NAV.Cavern_of_Corrosion) + self.dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion) relic = self.get_double_rogue_remain() with self.config.multi_set(): self.config.stored.DungeonDouble.calyx = calyx diff --git a/tasks/dungeon/keywords/dungeon.py b/tasks/dungeon/keywords/dungeon.py index 90c4c95f9..8a8648b64 100644 --- a/tasks/dungeon/keywords/dungeon.py +++ b/tasks/dungeon/keywords/dungeon.py @@ -3,112 +3,112 @@ 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_Jarilo_VI = DungeonList( +Calyx_Golden_Memories_Penacony = DungeonList( id=1, - name='Calyx_Golden_Memories_Jarilo_VI', - cn='回忆之蕾•雅利洛-Ⅵ', - cht='回憶之蕾•雅利洛-Ⅵ', - en='Bud of Memories (Jarilo-Ⅵ)', - jp='回憶の蕾・ヤリーロ-Ⅵ', - es='Flor de los recuerdos (Jarilo-Ⅵ)', - dungeon_id=1001, - plane_id=2010101, + name='Calyx_Golden_Memories_Penacony', + cn='回忆之蕾', + cht='回憶之蕾', + en='Bud of Memories', + jp='回憶の蕾', + es='Flor de los recuerdos', + dungeon_id=1014, + plane_id=2031301, ) -Calyx_Golden_Aether_Jarilo_VI = DungeonList( +Calyx_Golden_Aether_Penacony = DungeonList( id=2, - name='Calyx_Golden_Aether_Jarilo_VI', - cn='以太之蕾•雅利洛-Ⅵ', - cht='乙太之蕾•雅利洛-Ⅵ', - en='Bud of Aether (Jarilo-Ⅵ)', - jp='エーテルの蕾・ヤリーロ-Ⅵ', - es='Flor de éter (Jarilo-Ⅵ)', - dungeon_id=1002, - plane_id=2011101, + name='Calyx_Golden_Aether_Penacony', + cn='以太之蕾', + cht='乙太之蕾', + en='Bud of Aether', + jp='エーテルの蕾', + es='Flor de éter', + dungeon_id=1015, + plane_id=2031201, ) -Calyx_Golden_Treasures_Jarilo_VI = DungeonList( +Calyx_Golden_Treasures_Penacony = DungeonList( id=3, - name='Calyx_Golden_Treasures_Jarilo_VI', - cn='藏珍之蕾•雅利洛-Ⅵ', - cht='藏珍之蕾•雅利洛-Ⅵ', - en='Bud of Treasures (Jarilo-Ⅵ)', - jp='秘蔵の蕾・ヤリーロ-Ⅵ', - es='Flor de tesoros (Jarilo-Ⅵ)', - dungeon_id=1003, - plane_id=2012101, + name='Calyx_Golden_Treasures_Penacony', + cn='藏珍之蕾', + cht='藏珍之蕾', + en='Bud of Treasures', + jp='秘蔵の蕾', + es='Flor de tesoros', + dungeon_id=1016, + plane_id=2031101, ) Calyx_Golden_Memories_The_Xianzhou_Luofu = DungeonList( id=4, 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)', + cn='回忆之蕾', + cht='回憶之蕾', + en='Bud of Memories', + jp='回憶の蕾', + es='Flor de los recuerdos', dungeon_id=1011, 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)', + cn='以太之蕾', + cht='乙太之蕾', + en='Bud of Aether', + jp='エーテルの蕾', + es='Flor de éter', dungeon_id=1012, 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)', + cn='藏珍之蕾', + cht='藏珍之蕾', + en='Bud of Treasures', + jp='秘蔵の蕾', + es='Flor de tesoros', dungeon_id=1013, plane_id=2022201, ) -Calyx_Golden_Memories_Penacony = DungeonList( +Calyx_Golden_Memories_Jarilo_VI = DungeonList( id=7, - name='Calyx_Golden_Memories_Penacony', - cn='回忆之蕾•匹诺康尼', - cht='回憶之蕾•匹諾康尼', - en='Bud of Memories (Penacony)', - jp='回憶の蕾・ピノコニー', - es='Flor de los recuerdos (Colonipenal)', - dungeon_id=1014, - plane_id=2031301, + name='Calyx_Golden_Memories_Jarilo_VI', + cn='回忆之蕾', + cht='回憶之蕾', + en='Bud of Memories', + jp='回憶の蕾', + es='Flor de los recuerdos', + dungeon_id=1001, + plane_id=2010101, ) -Calyx_Golden_Aether_Penacony = DungeonList( +Calyx_Golden_Aether_Jarilo_VI = DungeonList( id=8, - name='Calyx_Golden_Aether_Penacony', - cn='以太之蕾•匹诺康尼', - cht='乙太之蕾•匹諾康尼', - en='Bud of Aether (Penacony)', - jp='エーテルの蕾・ピノコニー', - es='Flor de éter (Colonipenal)', - dungeon_id=1015, - plane_id=2031201, + name='Calyx_Golden_Aether_Jarilo_VI', + cn='以太之蕾', + cht='乙太之蕾', + en='Bud of Aether', + jp='エーテルの蕾', + es='Flor de éter', + dungeon_id=1002, + plane_id=2011101, ) -Calyx_Golden_Treasures_Penacony = DungeonList( +Calyx_Golden_Treasures_Jarilo_VI = DungeonList( id=9, - name='Calyx_Golden_Treasures_Penacony', - cn='藏珍之蕾•匹诺康尼', - cht='藏珍之蕾•匹諾康尼', - en='Bud of Treasures (Penacony)', - jp='秘蔵の蕾・ピノコニー', - es='Flor de tesoros (Colonipenal)', - dungeon_id=1016, - plane_id=2031101, + name='Calyx_Golden_Treasures_Jarilo_VI', + cn='藏珍之蕾', + cht='藏珍之蕾', + en='Bud of Treasures', + jp='秘蔵の蕾', + es='Flor de tesoros', + dungeon_id=1003, + plane_id=2012101, ) Calyx_Crimson_Destruction_Herta_StorageZone = DungeonList( id=10, name='Calyx_Crimson_Destruction_Herta_StorageZone', - cn='毁灭之蕾•拟造花萼(赤)', - cht='毀滅之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Destruction', - jp='疑似花萼(赤)・壊滅の蕾', + cn='毁灭之蕾', + cht='毀滅之蕾', + en='Bud of Destruction', + jp='壊滅の蕾', es='Flor de la Destrucción', dungeon_id=1004, plane_id=2000201, @@ -116,10 +116,10 @@ Calyx_Crimson_Destruction_Herta_StorageZone = DungeonList( Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape = DungeonList( id=11, name='Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape', - cn='毁灭之蕾•拟造花萼(赤)', - cht='毀滅之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Destruction', - jp='疑似花萼(赤)・壊滅の蕾', + cn='毁灭之蕾', + cht='毀滅之蕾', + en='Bud of Destruction', + jp='壊滅の蕾', es='Flor de la Destrucción', dungeon_id=1018, plane_id=2023201, @@ -127,10 +127,10 @@ Calyx_Crimson_Destruction_Luofu_ScalegorgeWaterscape = DungeonList( Calyx_Crimson_Preservation_Herta_SupplyZone = DungeonList( id=12, name='Calyx_Crimson_Preservation_Herta_SupplyZone', - cn='存护之蕾•拟造花萼(赤)', - cht='存護之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Preservation', - jp='疑似花萼(赤)・存護の蕾', + cn='存护之蕾', + cht='存護之蕾', + en='Bud of Preservation', + jp='存護の蕾', es='Flor de la Conservación', dungeon_id=1005, plane_id=2000301, @@ -138,10 +138,10 @@ Calyx_Crimson_Preservation_Herta_SupplyZone = DungeonList( Calyx_Crimson_Preservation_Penacony_ClockStudiosThemePark = DungeonList( id=13, name='Calyx_Crimson_Preservation_Penacony_ClockStudiosThemePark', - cn='存护之蕾•拟造花萼(赤)', - cht='存護之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Preservation', - jp='疑似花萼(赤)・存護の蕾', + cn='存护之蕾', + cht='存護之蕾', + en='Bud of Preservation', + jp='存護の蕾', es='Flor de la Conservación', dungeon_id=1020, plane_id=2032101, @@ -149,10 +149,10 @@ Calyx_Crimson_Preservation_Penacony_ClockStudiosThemePark = DungeonList( Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains = DungeonList( id=14, name='Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains', - cn='巡猎之蕾•拟造花萼(赤)', - cht='巡獵之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of The Hunt', - jp='疑似花萼(赤)・巡狩の蕾', + cn='巡猎之蕾', + cht='巡獵之蕾', + en='Bud of The Hunt', + jp='巡狩の蕾', es='Flor de la Cacería', dungeon_id=1006, plane_id=2010101, @@ -160,10 +160,10 @@ Calyx_Crimson_The_Hunt_Jarilo_OutlyingSnowPlains = DungeonList( Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue = DungeonList( id=15, name='Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue', - cn='巡猎之蕾•拟造花萼(赤)', - cht='巡獵之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of The Hunt', - jp='疑似花萼(赤)・巡狩の蕾', + cn='巡猎之蕾', + cht='巡獵之蕾', + en='Bud of The Hunt', + jp='巡狩の蕾', es='Flor de la Cacería', dungeon_id=1022, plane_id=2033101, @@ -171,10 +171,10 @@ Calyx_Crimson_The_Hunt_Penacony_SoulGladScorchsandAuditionVenue = DungeonList( Calyx_Crimson_Abundance_Jarilo_BackwaterPass = DungeonList( id=16, name='Calyx_Crimson_Abundance_Jarilo_BackwaterPass', - cn='丰饶之蕾•拟造花萼(赤)', - cht='豐饒之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Abundance', - jp='疑似花萼(赤)・豊穣の蕾', + cn='丰饶之蕾', + cht='豐饒之蕾', + en='Bud of Abundance', + jp='豊穣の蕾', es='Flor de la Abundancia', dungeon_id=1007, plane_id=2011101, @@ -182,10 +182,10 @@ Calyx_Crimson_Abundance_Jarilo_BackwaterPass = DungeonList( Calyx_Crimson_Abundance_Luofu_FyxestrollGarden = DungeonList( id=17, name='Calyx_Crimson_Abundance_Luofu_FyxestrollGarden', - cn='丰饶之蕾•拟造花萼(赤)', - cht='豐饒之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Abundance', - jp='疑似花萼(赤)・豊穣の蕾', + cn='丰饶之蕾', + cht='豐饒之蕾', + en='Bud of Abundance', + jp='豊穣の蕾', es='Flor de la Abundancia', dungeon_id=1021, plane_id=2022301, @@ -193,10 +193,10 @@ Calyx_Crimson_Abundance_Luofu_FyxestrollGarden = DungeonList( Calyx_Crimson_Erudition_Jarilo_RivetTown = DungeonList( id=18, name='Calyx_Crimson_Erudition_Jarilo_RivetTown', - cn='智识之蕾•拟造花萼(赤)', - cht='智識之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Erudition', - jp='疑似花萼(赤)・知恵の蕾', + cn='智识之蕾', + cht='智識之蕾', + en='Bud of Erudition', + jp='知恵の蕾', es='Flor de la Erudición', dungeon_id=1008, plane_id=2012201, @@ -204,10 +204,10 @@ Calyx_Crimson_Erudition_Jarilo_RivetTown = DungeonList( Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater = DungeonList( id=19, name='Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater', - cn='智识之蕾•拟造花萼(赤)', - cht='智識之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Erudition', - jp='疑似花萼(赤)・知恵の蕾', + cn='智识之蕾', + cht='智識之蕾', + en='Bud of Erudition', + jp='知恵の蕾', es='Flor de la Erudición', dungeon_id=1023, plane_id=2033201, @@ -215,10 +215,10 @@ Calyx_Crimson_Erudition_Penacony_PenaconyGrandTheater = DungeonList( Calyx_Crimson_Harmony_Jarilo_RobotSettlement = DungeonList( id=20, name='Calyx_Crimson_Harmony_Jarilo_RobotSettlement', - cn='同谐之蕾•拟造花萼(赤)', - cht='同諧之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Harmony', - jp='疑似花萼(赤)・調和の蕾', + cn='同谐之蕾', + cht='同諧之蕾', + en='Bud of Harmony', + jp='調和の蕾', es='Flor de la Armonía', dungeon_id=1009, plane_id=2012301, @@ -226,10 +226,10 @@ Calyx_Crimson_Harmony_Jarilo_RobotSettlement = DungeonList( Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape = DungeonList( id=21, name='Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape', - cn='同谐之蕾•拟造花萼(赤)', - cht='同諧之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Harmony', - jp='疑似花萼(赤)・調和の蕾', + cn='同谐之蕾', + cht='同諧之蕾', + en='Bud of Harmony', + jp='調和の蕾', es='Flor de la Armonía', dungeon_id=1019, plane_id=2031101, @@ -237,10 +237,10 @@ Calyx_Crimson_Harmony_Penacony_TheReverieDreamscape = DungeonList( Calyx_Crimson_Nihility_Jarilo_GreatMine = DungeonList( id=22, name='Calyx_Crimson_Nihility_Jarilo_GreatMine', - cn='虚无之蕾•拟造花萼(赤)', - cht='虛無之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Nihility', - jp='疑似花萼(赤)・虚無の蕾', + cn='虚无之蕾', + cht='虛無之蕾', + en='Bud of Nihility', + jp='虚無の蕾', es='Flor de la Nihilidad', dungeon_id=1010, plane_id=2012101, @@ -248,10 +248,10 @@ Calyx_Crimson_Nihility_Jarilo_GreatMine = DungeonList( Calyx_Crimson_Nihility_Luofu_AlchemyCommission = DungeonList( id=23, name='Calyx_Crimson_Nihility_Luofu_AlchemyCommission', - cn='虚无之蕾•拟造花萼(赤)', - cht='虛無之蕾•擬造花萼(赤)', - en='Calyx (Crimson): Bud of Nihility', - jp='疑似花萼(赤)・虚無の蕾', + cn='虚无之蕾', + cht='虛無之蕾', + en='Bud of Nihility', + jp='虚無の蕾', es='Flor de la Nihilidad', dungeon_id=1017, plane_id=2023101, @@ -259,10 +259,10 @@ Calyx_Crimson_Nihility_Luofu_AlchemyCommission = DungeonList( Stagnant_Shadow_Quanta = DungeonList( id=24, name='Stagnant_Shadow_Quanta', - cn='空海之形•凝滞虚影', - cht='空海之形•凝滯虛影', - en='Stagnant Shadow: Shape of Quanta', - jp='凝結虚影・虚海の形', + cn='空海之形', + cht='空海之形', + en='Shape of Quanta', + jp='虚海の形', es='Forma del cuanto', dungeon_id=1101, plane_id=2000101, @@ -270,10 +270,10 @@ Stagnant_Shadow_Quanta = DungeonList( Stagnant_Shadow_Gust = DungeonList( id=25, name='Stagnant_Shadow_Gust', - cn='巽风之形•凝滞虚影', - cht='巽風之形•凝滯虛影', - en='Stagnant Shadow: Shape of Gust', - jp='凝結虚影・薫風の形', + cn='巽风之形', + cht='巽風之形', + en='Shape of Gust', + jp='薫風の形', es='Forma del aire', dungeon_id=1102, plane_id=2012201, @@ -281,10 +281,10 @@ Stagnant_Shadow_Gust = DungeonList( Stagnant_Shadow_Fulmination = DungeonList( id=26, name='Stagnant_Shadow_Fulmination', - cn='鸣雷之形•凝滞虚影', - cht='鳴雷之形•凝滯虛影', - en='Stagnant Shadow: Shape of Fulmination', - jp='凝結虚影・鳴雷の形', + cn='鸣雷之形', + cht='鳴雷之形', + en='Shape of Fulmination', + jp='鳴雷の形', es='Forma del trueno', dungeon_id=1103, plane_id=2013201, @@ -292,10 +292,10 @@ Stagnant_Shadow_Fulmination = DungeonList( Stagnant_Shadow_Blaze = DungeonList( id=27, name='Stagnant_Shadow_Blaze', - cn='炎华之形•凝滞虚影', - cht='炎華之形•凝滯虛影', - en='Stagnant Shadow: Shape of Blaze', - jp='凝結虚影・炎華の形', + cn='炎华之形', + cht='炎華之形', + en='Shape of Blaze', + jp='炎華の形', es='Forma de las llamas', dungeon_id=1104, plane_id=2013101, @@ -303,10 +303,10 @@ Stagnant_Shadow_Blaze = DungeonList( Stagnant_Shadow_Spike = DungeonList( id=28, name='Stagnant_Shadow_Spike', - cn='锋芒之形•凝滞虚影', - cht='鋒芒之形•凝滯虛影', - en='Stagnant Shadow: Shape of Spike', - jp='凝結虚影・切先の形', + cn='锋芒之形', + cht='鋒芒之形', + en='Shape of Spike', + jp='切先の形', es='Forma afilada', dungeon_id=1105, plane_id=2012101, @@ -314,10 +314,10 @@ Stagnant_Shadow_Spike = DungeonList( Stagnant_Shadow_Rime = DungeonList( id=29, name='Stagnant_Shadow_Rime', - cn='霜晶之形•凝滞虚影', - cht='霜晶之形•凝滯虛影', - en='Stagnant Shadow: Shape of Rime', - jp='凝結虚影・霜晶の形', + cn='霜晶之形', + cht='霜晶之形', + en='Shape of Rime', + jp='霜晶の形', es='Forma de la escarcha', dungeon_id=1106, plane_id=2013201, @@ -325,10 +325,10 @@ Stagnant_Shadow_Rime = DungeonList( Stagnant_Shadow_Mirage = DungeonList( id=30, name='Stagnant_Shadow_Mirage', - cn='幻光之形•凝滞虚影', - cht='幻光之形•凝滯虛影', - en='Stagnant Shadow: Shape of Mirage', - jp='凝結虚影・幻光の形', + cn='幻光之形', + cht='幻光之形', + en='Shape of Mirage', + jp='幻光の形', es='Forma del espejismo', dungeon_id=1107, plane_id=2011101, @@ -336,10 +336,10 @@ Stagnant_Shadow_Mirage = DungeonList( Stagnant_Shadow_Icicle = DungeonList( id=31, name='Stagnant_Shadow_Icicle', - cn='冰棱之形•凝滞虚影', - cht='冰稜之形•凝滯虛影', - en='Stagnant Shadow: Shape of Icicle', - jp='凝結虚影・氷柱の形', + cn='冰棱之形', + cht='冰稜之形', + en='Shape of Icicle', + jp='氷柱の形', es='Forma del témpano', dungeon_id=1108, plane_id=2021101, @@ -347,10 +347,10 @@ Stagnant_Shadow_Icicle = DungeonList( Stagnant_Shadow_Doom = DungeonList( id=32, name='Stagnant_Shadow_Doom', - cn='震厄之形•凝滞虚影', - cht='震厄之形•凝滯虛影', - en='Stagnant Shadow: Shape of Doom', - jp='凝結虚影・震厄の形', + cn='震厄之形', + cht='震厄之形', + en='Shape of Doom', + jp='震厄の形', es='Forma de la perdición', dungeon_id=1109, plane_id=2021201, @@ -358,10 +358,10 @@ Stagnant_Shadow_Doom = DungeonList( Stagnant_Shadow_Puppetry = DungeonList( id=33, name='Stagnant_Shadow_Puppetry', - cn='偃偶之形•凝滞虚影', - cht='偃偶之形•凝滯虛影', - en='Stagnant Shadow: Shape of Puppetry', - jp='凝結虚影・傀儡の形', + cn='偃偶之形', + cht='偃偶之形', + en='Shape of Puppetry', + jp='傀儡の形', es='Forma de las marionetas', dungeon_id=1110, plane_id=2022201, @@ -369,10 +369,10 @@ Stagnant_Shadow_Puppetry = DungeonList( Stagnant_Shadow_Abomination = DungeonList( id=34, name='Stagnant_Shadow_Abomination', - cn='孽兽之形•凝滞虚影', - cht='孽獸之形•凝滯虛影', - en='Stagnant Shadow: Shape of Abomination', - jp='凝結虚影・厄獣の形', + cn='孽兽之形', + cht='孽獸之形', + en='Shape of Abomination', + jp='厄獣の形', es='Forma de la abominación', dungeon_id=1111, plane_id=2023201, @@ -380,10 +380,10 @@ Stagnant_Shadow_Abomination = DungeonList( Stagnant_Shadow_Scorch = DungeonList( id=35, name='Stagnant_Shadow_Scorch', - cn='燔灼之形•凝滞虚影', - cht='燔灼之形•凝滯虛影', - en='Stagnant Shadow: Shape of Scorch', - jp='凝結虚影・燔灼の形', + cn='燔灼之形', + cht='燔灼之形', + en='Shape of Scorch', + jp='燔灼の形', es='Forma abrasada', dungeon_id=1112, plane_id=2012101, @@ -391,10 +391,10 @@ Stagnant_Shadow_Scorch = DungeonList( Stagnant_Shadow_Celestial = DungeonList( id=36, name='Stagnant_Shadow_Celestial', - cn='天人之形•凝滞虚影', - cht='天人之形•凝滯虛影', - en='Stagnant Shadow: Shape of Celestial', - jp='凝結虚影・天人の形', + cn='天人之形', + cht='天人之形', + en='Shape of Celestial', + jp='天人の形', es='Forma de lo celestial', dungeon_id=1113, plane_id=2023101, @@ -402,10 +402,10 @@ Stagnant_Shadow_Celestial = DungeonList( Stagnant_Shadow_Perdition = DungeonList( id=37, name='Stagnant_Shadow_Perdition', - cn='幽府之形•凝滞虚影', - cht='幽府之形•凝滯虛影', - en='Stagnant Shadow: Shape of Perdition', - jp='凝結虚影・幽府の形', + cn='幽府之形', + cht='幽府之形', + en='Shape of Perdition', + jp='幽府の形', es='Forma del aislamiento', dungeon_id=1114, plane_id=2022301, @@ -413,10 +413,10 @@ Stagnant_Shadow_Perdition = DungeonList( Stagnant_Shadow_Nectar = DungeonList( id=38, name='Stagnant_Shadow_Nectar', - cn='冰酿之形•凝滞虚影', - cht='冰釀之形•凝滯虛影', - en='Stagnant Shadow: Shape of Nectar', - jp='凝結虚影・氷醸の形', + cn='冰酿之形', + cht='冰釀之形', + en='Shape of Nectar', + jp='氷醸の形', es='Forma del néctar', dungeon_id=1115, plane_id=2031101, @@ -424,10 +424,10 @@ Stagnant_Shadow_Nectar = DungeonList( Stagnant_Shadow_Roast = DungeonList( id=39, name='Stagnant_Shadow_Roast', - cn='焦炙之形•凝滞虚影', - cht='焦炙之形•凝滯虛影', - en='Stagnant Shadow: Shape of Roast', - jp='凝結虚影・焦灼の形', + cn='焦炙之形', + cht='焦炙之形', + en='Shape of Roast', + jp='焦灼の形', es='Forma del agostamiento', dungeon_id=1116, plane_id=2031301, @@ -435,10 +435,10 @@ Stagnant_Shadow_Roast = DungeonList( Stagnant_Shadow_Ire = DungeonList( id=40, name='Stagnant_Shadow_Ire', - cn='嗔怒之形•凝滞虚影', - cht='嗔怒之形•凝滯虛影', - en='Stagnant Shadow: Shape of Ire', - jp='凝結虚影・憤怒の形', + cn='嗔怒之形', + cht='嗔怒之形', + en='Shape of Ire', + jp='憤怒の形', es='Forma de la ira', dungeon_id=1117, plane_id=2032201, @@ -446,170 +446,159 @@ Stagnant_Shadow_Ire = DungeonList( Stagnant_Shadow_Duty = DungeonList( id=41, name='Stagnant_Shadow_Duty', - cn='职司之形•凝滞虚影', - cht='職司之形•凝滯虛影', - en='Stagnant Shadow: Shape of Duty', - jp='凝結虚影・職掌の形', + cn='职司之形', + cht='職司之形', + en='Shape of Duty', + jp='職掌の形', es='Forma del deber', dungeon_id=1118, plane_id=2032101, ) -Cavern_of_Corrosion_Path_of_Gelid_Wind = DungeonList( +Stagnant_Shadow_Mechwolf = DungeonList( id=42, - name='Cavern_of_Corrosion_Path_of_Gelid_Wind', - cn='霜风之径•侵蚀隧洞', - cht='霜風之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Gelid Wind', - jp='侵蝕トンネル・霜風の路', - es='Senda del viento gélido', - dungeon_id=1201, - plane_id=2000201, + name='Stagnant_Shadow_Mechwolf', + cn='机狼之形', + cht='機狼之形', + en='Shape of Mechwolf', + jp='機狼の形', + es='Forma del lobo mecánico', + dungeon_id=1120, + plane_id=2024101, ) -Cavern_of_Corrosion_Path_of_Jabbing_Punch = DungeonList( +Stagnant_Shadow_Gloam = DungeonList( id=43, - name='Cavern_of_Corrosion_Path_of_Jabbing_Punch', - cn='迅拳之径•侵蚀隧洞', - cht='迅拳之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Jabbing Punch', - jp='侵蝕トンネル・迅拳の路', - es='Senda de los puños rápidos', - dungeon_id=1202, - plane_id=2013101, -) -Cavern_of_Corrosion_Path_of_Drifting = DungeonList( - id=44, - name='Cavern_of_Corrosion_Path_of_Drifting', - cn='漂泊之径•侵蚀隧洞', - cht='漂泊之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Drifting', - jp='侵蝕トンネル・漂泊の路', - es='Senda de la deriva', - dungeon_id=1203, - plane_id=2013201, -) -Cavern_of_Corrosion_Path_of_Providence = DungeonList( - id=45, - name='Cavern_of_Corrosion_Path_of_Providence', - cn='睿治之径•侵蚀隧洞', - cht='睿治之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Providence', - jp='侵蝕トンネル・睿治の路', - es='Senda de la providencia', - dungeon_id=1204, - plane_id=2013401, -) -Cavern_of_Corrosion_Path_of_Holy_Hymn = DungeonList( - id=46, - name='Cavern_of_Corrosion_Path_of_Holy_Hymn', - cn='圣颂之径•侵蚀隧洞', - cht='聖頌之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Holy Hymn', - jp='侵蝕トンネル・聖頌の路', - es='Senda del himno sagrado', - dungeon_id=1205, - plane_id=2021101, -) -Cavern_of_Corrosion_Path_of_Conflagration = DungeonList( - id=47, - name='Cavern_of_Corrosion_Path_of_Conflagration', - cn='野焰之径•侵蚀隧洞', - cht='野焰之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Conflagration', - jp='侵蝕トンネル・野焔の路', - es='Senda de la conflagración', - dungeon_id=1206, - plane_id=2021201, -) -Cavern_of_Corrosion_Path_of_Elixir_Seekers = DungeonList( - id=48, - name='Cavern_of_Corrosion_Path_of_Elixir_Seekers', - cn='药使之径•侵蚀隧洞', - cht='藥使之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Elixir Seekers', - jp='侵蝕トンネル・薬使の路', - es='Senda de los elixires', - dungeon_id=1207, - plane_id=2023101, -) -Cavern_of_Corrosion_Path_of_Darkness = DungeonList( - id=49, - name='Cavern_of_Corrosion_Path_of_Darkness', - cn='幽冥之径•侵蚀隧洞', - cht='幽冥之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Darkness', - jp='侵蝕トンネル・幽冥の路', - es='Senda de la oscuridad', - dungeon_id=1208, - plane_id=2022301, -) -Cavern_of_Corrosion_Path_of_Dreamdive = DungeonList( - id=50, - name='Cavern_of_Corrosion_Path_of_Dreamdive', - cn='梦潜之径•侵蚀隧洞', - cht='夢潛之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Dreamdive', - jp='侵蝕トンネル・夢潜の路', - es='Senda de los sueños', - dungeon_id=1209, - plane_id=2031101, + name='Stagnant_Shadow_Gloam', + cn='今宵之形', + cht='今宵之形', + en='Shape of Gloam', + jp='今宵の形', + es='Forma del ocaso', + dungeon_id=1121, + plane_id=2033201, ) Cavern_of_Corrosion_Path_of_Cavalier = DungeonList( - id=51, + id=44, name='Cavern_of_Corrosion_Path_of_Cavalier', - cn='勇骑之径•侵蚀隧洞', - cht='勇騎之徑•侵蝕隧洞', - en='Cavern of Corrosion: Path of Cavalier', - jp='侵蝕トンネル・勇騎の路', + cn='勇骑之径', + cht='勇騎之徑', + en='Path of Cavalier', + jp='勇騎の路', es='Senda del caballero', dungeon_id=1210, plane_id=2033201, ) -Echo_of_War_Destruction_Beginning = DungeonList( - id=52, - name='Echo_of_War_Destruction_Beginning', - cn='毁灭的开端•历战余响', - cht='毀滅的開端•歷戰餘響', - en="Echo of War: Destruction's Beginning", - jp='歴戦余韻・壊滅の始まり', - es='El principio de la Destrucción', - dungeon_id=1301, - plane_id=2000301, +Cavern_of_Corrosion_Path_of_Dreamdive = DungeonList( + id=45, + name='Cavern_of_Corrosion_Path_of_Dreamdive', + cn='梦潜之径', + cht='夢潛之徑', + en='Path of Dreamdive', + jp='夢潜の路', + es='Senda de los sueños', + dungeon_id=1209, + plane_id=2031101, ) -Echo_of_War_End_of_the_Eternal_Freeze = DungeonList( - id=53, - name='Echo_of_War_End_of_the_Eternal_Freeze', - cn='寒潮的落幕•历战余响', - cht='寒潮的落幕•歷戰餘響', - en='Echo of War: End of the Eternal Freeze', - jp='歴戦余韻・寒波の幕切れ', - es='El fin del Hielo Eterno', - dungeon_id=1302, +Cavern_of_Corrosion_Path_of_Darkness = DungeonList( + id=46, + name='Cavern_of_Corrosion_Path_of_Darkness', + cn='幽冥之径', + cht='幽冥之徑', + en='Path of Darkness', + jp='幽冥の路', + es='Senda de la oscuridad', + dungeon_id=1208, + plane_id=2022301, +) +Cavern_of_Corrosion_Path_of_Elixir_Seekers = DungeonList( + id=47, + name='Cavern_of_Corrosion_Path_of_Elixir_Seekers', + cn='药使之径', + cht='藥使之徑', + en='Path of Elixir Seekers', + jp='薬使の路', + es='Senda de los elixires', + dungeon_id=1207, + plane_id=2023101, +) +Cavern_of_Corrosion_Path_of_Conflagration = DungeonList( + id=48, + name='Cavern_of_Corrosion_Path_of_Conflagration', + cn='野焰之径', + cht='野焰之徑', + en='Path of Conflagration', + jp='野焔の路', + es='Senda de la conflagración', + dungeon_id=1206, + plane_id=2021201, +) +Cavern_of_Corrosion_Path_of_Holy_Hymn = DungeonList( + id=49, + name='Cavern_of_Corrosion_Path_of_Holy_Hymn', + cn='圣颂之径', + cht='聖頌之徑', + en='Path of Holy Hymn', + jp='聖頌の路', + es='Senda del himno sagrado', + dungeon_id=1205, + plane_id=2021101, +) +Cavern_of_Corrosion_Path_of_Providence = DungeonList( + id=50, + name='Cavern_of_Corrosion_Path_of_Providence', + cn='睿治之径', + cht='睿治之徑', + en='Path of Providence', + jp='睿治の路', + es='Senda de la providencia', + dungeon_id=1204, plane_id=2013401, ) -Echo_of_War_Divine_Seed = DungeonList( - id=54, - name='Echo_of_War_Divine_Seed', - cn='不死的神实•历战余响', - cht='不死的神實•歷戰餘響', - en='Echo of War: Divine Seed', - jp='歴戦余韻・不死の神実', - es='Semilla divina', - dungeon_id=1303, - plane_id=2023201, +Cavern_of_Corrosion_Path_of_Drifting = DungeonList( + id=51, + name='Cavern_of_Corrosion_Path_of_Drifting', + cn='漂泊之径', + cht='漂泊之徑', + en='Path of Drifting', + jp='漂泊の路', + es='Senda de la deriva', + dungeon_id=1203, + plane_id=2013201, ) -Echo_of_War_Borehole_Planet_Old_Crater = DungeonList( - id=55, - name='Echo_of_War_Borehole_Planet_Old_Crater', - cn='蛀星的旧靥•历战余响', - cht='蛀星的舊靨•歷戰餘響', - en="Echo of War: Borehole Planet's Old Crater", - jp='歴戦余韻・星を蝕む往日の面影', - es='Cráter del planeta devorado', - dungeon_id=1304, - plane_id=2000401, +Cavern_of_Corrosion_Path_of_Jabbing_Punch = DungeonList( + id=52, + name='Cavern_of_Corrosion_Path_of_Jabbing_Punch', + cn='迅拳之径', + cht='迅拳之徑', + en='Path of Jabbing Punch', + jp='迅拳の路', + es='Senda de los puños rápidos', + dungeon_id=1202, + plane_id=2013101, +) +Cavern_of_Corrosion_Path_of_Gelid_Wind = DungeonList( + id=53, + name='Cavern_of_Corrosion_Path_of_Gelid_Wind', + cn='霜风之径', + cht='霜風之徑', + en='Path of Gelid Wind', + jp='霜風の路', + es='Senda del viento gélido', + dungeon_id=1201, + plane_id=2000201, +) +Echo_of_War_Inner_Beast_Battlefield = DungeonList( + id=54, + name='Echo_of_War_Inner_Beast_Battlefield', + cn='心兽的战场•历战余响', + cht='心獸的戰場•歷戰餘響', + en="Echo of War: Inner Beast's Battlefield", + jp='歴戦余韻・心獣の戦場', + es='Campo de batalla de la bestia interior', + dungeon_id=1306, + plane_id=2024201, ) Echo_of_War_Salutations_of_Ashen_Dreams = DungeonList( - id=56, + id=55, name='Echo_of_War_Salutations_of_Ashen_Dreams', cn='尘梦的赞礼•历战余响', cht='塵夢的讚禮•歷戰餘響', @@ -619,184 +608,239 @@ Echo_of_War_Salutations_of_Ashen_Dreams = DungeonList( dungeon_id=1305, plane_id=2033201, ) -Simulated_Universe_World_1 = DungeonList( +Echo_of_War_Borehole_Planet_Old_Crater = DungeonList( + id=56, + name='Echo_of_War_Borehole_Planet_Old_Crater', + cn='蛀星的旧靥•历战余响', + cht='蛀星的舊靨•歷戰餘響', + en="Echo of War: Borehole Planet's Old Crater", + jp='歴戦余韻・星を蝕む往日の面影', + es='Cráter del planeta devorado', + dungeon_id=1304, + plane_id=2000401, +) +Echo_of_War_Divine_Seed = DungeonList( id=57, + name='Echo_of_War_Divine_Seed', + cn='不死的神实•历战余响', + cht='不死的神實•歷戰餘響', + en='Echo of War: Divine Seed', + jp='歴戦余韻・不死の神実', + es='Semilla divina', + dungeon_id=1303, + plane_id=2023201, +) +Echo_of_War_End_of_the_Eternal_Freeze = DungeonList( + id=58, + name='Echo_of_War_End_of_the_Eternal_Freeze', + cn='寒潮的落幕•历战余响', + cht='寒潮的落幕•歷戰餘響', + en='Echo of War: End of the Eternal Freeze', + jp='歴戦余韻・寒波の幕切れ', + es='El fin del Hielo Eterno', + dungeon_id=1302, + plane_id=2013401, +) +Echo_of_War_Destruction_Beginning = DungeonList( + id=59, + name='Echo_of_War_Destruction_Beginning', + cn='毁灭的开端•历战余响', + cht='毀滅的開端•歷戰餘響', + en="Echo of War: Destruction's Beginning", + jp='歴戦余韻・壊滅の始まり', + es='El principio de la Destrucción', + dungeon_id=1301, + plane_id=2000301, +) +Simulated_Universe_World_1 = DungeonList( + id=60, name='Simulated_Universe_World_1', - cn='第一世界•模拟宇宙', - cht='第一世界•模擬宇宙', - en='Simulated Universe: World 1', - jp='第一世界・模擬宇宙', + cn='第一世界', + cht='第一世界', + en='World 1', + jp='第一世界', es='Mundo 1', dungeon_id=110, plane_id=100000104, ) Simulated_Universe_World_3 = DungeonList( - id=58, + id=61, name='Simulated_Universe_World_3', - cn='第三世界•模拟宇宙', - cht='第三世界•模擬宇宙', - en='Simulated Universe: World 3', - jp='第三世界・模擬宇宙', + cn='第三世界', + cht='第三世界', + en='World 3', + jp='第三世界', es='Mundo 3', dungeon_id=130, plane_id=100000104, ) Simulated_Universe_World_4 = DungeonList( - id=59, + id=62, name='Simulated_Universe_World_4', - cn='第四世界•模拟宇宙', - cht='第四世界•模擬宇宙', - en='Simulated Universe: World 4', - jp='第四世界・模擬宇宙', + cn='第四世界', + cht='第四世界', + en='World 4', + jp='第四世界', es='Mundo 4', dungeon_id=140, plane_id=100000104, ) Simulated_Universe_World_5 = DungeonList( - id=60, + id=63, name='Simulated_Universe_World_5', - cn='第五世界•模拟宇宙', - cht='第五世界•模擬宇宙', - en='Simulated Universe: World 5', - jp='第五世界・模擬宇宙', + cn='第五世界', + cht='第五世界', + en='World 5', + jp='第五世界', es='Mundo 5', dungeon_id=150, plane_id=100000104, ) Simulated_Universe_World_6 = DungeonList( - id=61, + id=64, name='Simulated_Universe_World_6', - cn='第六世界•模拟宇宙', - cht='第六世界•模擬宇宙', - en='Simulated Universe: World 6', - jp='第六世界・模擬宇宙', + cn='第六世界', + cht='第六世界', + en='World 6', + jp='第六世界', es='Mundo 6', dungeon_id=160, plane_id=100000104, ) Simulated_Universe_World_7 = DungeonList( - id=62, + id=65, name='Simulated_Universe_World_7', - cn='第七世界•模拟宇宙', - cht='第七世界•模擬宇宙', - en='Simulated Universe: World 7', - jp='第七世界・模擬宇宙', + cn='第七世界', + cht='第七世界', + en='World 7', + jp='第七世界', es='Mundo 7', dungeon_id=170, plane_id=100000104, ) Simulated_Universe_World_8 = DungeonList( - id=63, + id=66, name='Simulated_Universe_World_8', - cn='第八世界•模拟宇宙', - cht='第八世界•模擬宇宙', - en='Simulated Universe: World 8', - jp='第八世界・模擬宇宙', + cn='第八世界', + cht='第八世界', + en='World 8', + jp='第八世界', es='Mundo 8', dungeon_id=180, plane_id=100000104, ) Simulated_Universe_World_9 = DungeonList( - id=64, + id=67, name='Simulated_Universe_World_9', - cn='第九世界•模拟宇宙', - cht='第九世界•模擬宇宙', - en='Simulated Universe: World 9', - jp='第九世界・模擬宇宙', + cn='第九世界', + cht='第九世界', + en='World 9', + jp='第九世界', es='Mundo 9', dungeon_id=190, plane_id=100000104, ) +Divergent_Universe_Famished_Worker = DungeonList( + id=68, + name='Divergent_Universe_Famished_Worker', + cn='蠹役饥肠', + cht='蠹役飢腸', + en='Famished Worker', + jp='飢えた虫卒', + es='Obrero famélico', + dungeon_id=310, + plane_id=0, +) Divergent_Universe_Eternal_Comedy = DungeonList( - id=65, + id=69, name='Divergent_Universe_Eternal_Comedy', - cn='永恒笑剧•差分宇宙', - cht='永恆笑劇•差分宇宙', - en='Divergent Universe: Eternal Comedy', - jp='階差宇宙・永遠の喜劇', + cn='永恒笑剧', + cht='永恆笑劇', + en='Eternal Comedy', + jp='永遠の喜劇', es='Comedia eterna', dungeon_id=300, plane_id=0, ) Divergent_Universe_To_Sweet_Dreams = DungeonList( - id=66, + id=70, name='Divergent_Universe_To_Sweet_Dreams', - cn='伴你入眠•差分宇宙', - cht='伴你入眠•差分宇宙', - en='Divergent Universe: To Sweet Dreams', - jp='階差宇宙・寄り添い眠る', + cn='伴你入眠', + cht='伴你入眠', + en='To Sweet Dreams', + jp='寄り添い眠る', es='Hasta los dulces sueños', dungeon_id=290, plane_id=0, ) Divergent_Universe_Pouring_Blades = DungeonList( - id=67, + id=71, name='Divergent_Universe_Pouring_Blades', - cn='天剑如雨•差分宇宙', - cht='天劍如雨•差分宇宙', - en='Divergent Universe: Pouring Blades', - jp='階差宇宙・剣の雨', + cn='天剑如雨', + cht='天劍如雨', + en='Pouring Blades', + jp='剣の雨', es='Lluvia de espadas', dungeon_id=280, plane_id=0, ) Divergent_Universe_Fruit_of_Evil = DungeonList( - id=68, + id=72, name='Divergent_Universe_Fruit_of_Evil', - cn='孽果盘生•差分宇宙', - cht='孽果盤生•差分宇宙', - en='Divergent Universe: Fruit of Evil', - jp='階差宇宙・渦巻く罪', + cn='孽果盘生', + cht='孽果盤生', + en='Fruit of Evil', + jp='渦巻く罪', es='Fruta del desastre', dungeon_id=270, plane_id=0, ) Divergent_Universe_Permafrost = DungeonList( - id=69, + id=73, name='Divergent_Universe_Permafrost', - cn='百年冻土•差分宇宙', - cht='百年凍土•差分宇宙', - en='Divergent Universe: Permafrost', - jp='階差宇宙・永久凍土', + cn='百年冻土', + cht='百年凍土', + en='Permafrost', + jp='永久凍土', es='Permafrost', dungeon_id=260, plane_id=0, ) Divergent_Universe_Gentle_Words = DungeonList( - id=70, + id=74, name='Divergent_Universe_Gentle_Words', - cn='温柔话语•差分宇宙', - cht='溫柔話語•差分宇宙', - en='Divergent Universe: Gentle Words', - jp='階差宇宙・優しい言葉', + cn='温柔话语', + cht='溫柔話語', + en='Gentle Words', + jp='優しい言葉', es='Palabras amables', dungeon_id=250, plane_id=0, ) Divergent_Universe_Smelted_Heart = DungeonList( - id=71, + id=75, name='Divergent_Universe_Smelted_Heart', - cn='浴火钢心•差分宇宙', - cht='浴火鋼心•差分宇宙', - en='Divergent Universe: Smelted Heart', - jp='階差宇宙・鋼の意志', + cn='浴火钢心', + cht='浴火鋼心', + en='Smelted Heart', + jp='鋼の意志', es='Corazón de fundición', dungeon_id=240, plane_id=0, ) Divergent_Universe_Untoppled_Walls = DungeonList( - id=72, + id=76, name='Divergent_Universe_Untoppled_Walls', - cn='坚城不倒•差分宇宙', - cht='堅城不倒•差分宇宙', - en='Divergent Universe: Untoppled Walls', - jp='階差宇宙・不動の砦', + cn='坚城不倒', + cht='堅城不倒', + en='Untoppled Walls', + jp='不動の砦', es='Muros inquebrantables', dungeon_id=230, plane_id=0, ) Simulated_Universe_The_Swarm_Disaster = DungeonList( - id=73, + id=77, name='Simulated_Universe_The_Swarm_Disaster', cn='寰宇蝗灾', cht='寰宇蝗災', @@ -807,7 +851,7 @@ Simulated_Universe_The_Swarm_Disaster = DungeonList( plane_id=-1, ) Simulated_Universe_Gold_and_Gears = DungeonList( - id=74, + id=78, name='Simulated_Universe_Gold_and_Gears', cn='黄金与机械', cht='黃金與機械', @@ -818,7 +862,7 @@ Simulated_Universe_Gold_and_Gears = DungeonList( plane_id=-1, ) Memory_of_Chaos = DungeonList( - id=75, + id=79, name='Memory_of_Chaos', cn='混沌回忆', cht='混沌回憶', @@ -829,7 +873,7 @@ Memory_of_Chaos = DungeonList( plane_id=-1, ) The_Voyage_of_Navis_Astriger = DungeonList( - id=76, + id=80, name='The_Voyage_of_Navis_Astriger', cn='天艟求仙迷航录', cht='天艟求仙迷航錄', @@ -840,7 +884,7 @@ The_Voyage_of_Navis_Astriger = DungeonList( plane_id=-1, ) The_Last_Vestiges_of_Towering_Citadel = DungeonList( - id=77, + id=81, name='The_Last_Vestiges_of_Towering_Citadel', cn='永屹之城遗秘', cht='永屹之城遺秘', diff --git a/tasks/dungeon/keywords/dungeon_detailed.py b/tasks/dungeon/keywords/dungeon_detailed.py index ccff5bab3..f65a145a5 100644 --- a/tasks/dungeon/keywords/dungeon_detailed.py +++ b/tasks/dungeon/keywords/dungeon_detailed.py @@ -150,11 +150,11 @@ Stagnant_Shadow_Roast = DungeonDetailed( Stagnant_Shadow_Ire = DungeonDetailed( id=17, name='Stagnant_Shadow_Ire', - cn='角色晋阶材料:火(流萤 / 加拉赫 / 椒丘)', - cht='角色晉階材料:火(流螢 / 加拉赫 / 椒丘)', - en='Ascension: Fire (Firefly / Gallagher / Jiaoqiu)', - jp='キャラクター昇格素材:炎(ホタル / ギャラガー / 椒丘)', - es='Ascension: Fuego (Luciérnaga / Gallagher / Jiaoqiu)', + cn='角色晋阶材料:火(流萤 / 加拉赫 / 椒丘 / 灵砂)', + cht='角色晉階材料:火(流螢 / 加拉赫 / 椒丘 / 靈砂)', + en='Ascension: Fire (Firefly / Gallagher / Jiaoqiu / Lingsha)', + jp='キャラクター昇格素材:炎(ホタル / ギャラガー / 椒丘 / 霊砂)', + es='Ascension: Fuego (Luciérnaga / Gallagher / Jiaoqiu / Lingsha)', ) Stagnant_Shadow_Duty = DungeonDetailed( id=18, @@ -165,3 +165,21 @@ Stagnant_Shadow_Duty = DungeonDetailed( jp='キャラクター昇格素材:物理(ブートヒル / ロビン / 雲璃)', es='Ascension: Físico (Boothill / Robin / Yunli)', ) +Stagnant_Shadow_Mechwolf = DungeonDetailed( + id=19, + name='Stagnant_Shadow_Mechwolf', + cn='角色晋阶材料:雷(貊泽)', + cht='角色晉階材料:雷(貊澤)', + en='Ascension: Lightning (Moze)', + jp='キャラクター昇格素材:雷(モゼ)', + es='Ascension: Rayo (Moze)', +) +Stagnant_Shadow_Gloam = DungeonDetailed( + id=20, + name='Stagnant_Shadow_Gloam', + cn='角色晋阶材料:风(飞霄)', + cht='角色晉階材料:風(飛霄)', + en='Ascension: Wind (Feixiao)', + jp='キャラクター昇格素材:風(飛霄)', + es='Ascension: Viento (Feixiao)', +) diff --git a/tasks/dungeon/stamina.py b/tasks/dungeon/stamina.py index 41fd56354..092cd3bd7 100644 --- a/tasks/dungeon/stamina.py +++ b/tasks/dungeon/stamina.py @@ -6,7 +6,7 @@ from tasks.base.page import page_guide from tasks.combat.assets.assets_combat_stamina_status import ICON_SEARCH, IMMERSIFIER_ICON from tasks.dungeon.assets.assets_dungeon_stamina import * from tasks.dungeon.keywords import KEYWORDS_DUNGEON_TAB -from tasks.dungeon.ui import DungeonUI +from tasks.dungeon.ui.ui import DungeonUI class DungeonStamina(DungeonUI): diff --git a/tasks/dungeon/ui.py b/tasks/dungeon/ui.py deleted file mode 100644 index e558d038d..000000000 --- a/tasks/dungeon/ui.py +++ /dev/null @@ -1,770 +0,0 @@ -import re - -import cv2 -import numpy as np - -from module.base.base import ModuleBase -from module.base.button import ClickButton -from module.base.decorator import run_once -from module.base.timer import Timer -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, split_and_pair_buttons -from module.ui.draggable_list import DraggableList -from module.ui.switch import Switch -from tasks.base.page import page_guide -from tasks.combat.assets.assets_combat_interact import DUNGEON_COMBAT_INTERACT, DUNGEON_COMBAT_INTERACT_TEXT -from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE -from tasks.dungeon.assets.assets_dungeon_ui import * -from tasks.dungeon.assets.assets_dungeon_ui_rogue import * -from tasks.dungeon.keywords import ( - DungeonList, - DungeonNav, - DungeonTab, - KEYWORDS_DUNGEON_ENTRANCE, - KEYWORDS_DUNGEON_LIST, - KEYWORDS_DUNGEON_NAV, - KEYWORDS_DUNGEON_TAB -) -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): - SEARCH_BUTTON = TAB_SEARCH - - def add_state(self, state, check_button, click_button=None): - # Load search - if check_button is not None: - check_button.load_search(self.__class__.SEARCH_BUTTON.area) - if click_button is not None: - click_button.load_search(self.__class__.SEARCH_BUTTON.area) - return super().add_state(state, check_button, click_button) - - def click(self, state, main): - """ - Args: - state (str): - main (ModuleBase): - """ - button = self.get_data(state)['click_button'] - _ = main.appear(button) # Search button to load offset - main.device.click(button) - - -SWITCH_DUNGEON_TAB = DungeonTabSwitch('DungeonTab', is_selector=True) -SWITCH_DUNGEON_TAB.add_state( - KEYWORDS_DUNGEON_TAB.Operation_Briefing, - check_button=OPERATION_BRIEFING_CHECK, - click_button=OPERATION_BRIEFING_CLICK -) -SWITCH_DUNGEON_TAB.add_state( - KEYWORDS_DUNGEON_TAB.Daily_Training, - check_button=DAILY_TRAINING_CHECK, - click_button=DAILY_TRAINING_CLICK -) -SWITCH_DUNGEON_TAB.add_state( - KEYWORDS_DUNGEON_TAB.Survival_Index, - check_button=SURVIVAL_INDEX_CHECK, - click_button=SURVIVAL_INDEX_CLICK -) -SWITCH_DUNGEON_TAB.add_state( - KEYWORDS_DUNGEON_TAB.Simulated_Universe, - check_button=SIMULATED_UNIVERSE_CHECK, - click_button=SIMULATED_UNIVERSE_CLICK -) -SWITCH_DUNGEON_TAB.add_state( - KEYWORDS_DUNGEON_TAB.Treasures_Lightward, - check_button=TREASURES_LIGHTWARD_CHECK, - click_button=TREASURES_LIGHTWARD_CLICK -) - - -class OcrDungeonNav(Ocr): - def after_process(self, result): - result = super().after_process(result) - result = result.replace('#', '') - if self.lang == 'cn': - result = result.replace('萼喜', '萼') - result = result.replace('带', '滞') # 凝带虚影 - return result - - -class OcrDungeonList(Ocr): - def after_process(self, result): - # 乙太之蕾•雅利洛-Ⅵ - result = re.sub(r'-[VⅤ][IⅠ]', '-Ⅵ', result) - - # 苏乐达™热砂海选会场 - result = re.sub(r'(苏乐达|蘇樂達|SoulGlad|スラーダ|FelizAlma)[rtT]*M', r'\1', result) - - result = super().after_process(result) - - if self.lang == 'cn': - result = result.replace('翼', '巽') # 巽风之形 - result = result.replace('皖A0', '50').replace('皖', '') - # 燔灼之形•凝滞虚影 - result = result.replace('熠', '燔') - result = re.sub('^灼之形', '燔灼之形', result) - # 偃偶之形•凝滞虚影 - result = re.sub('^偶之形', '偃偶之形', result) - # 嗔怒之形•凝滞虚影 - 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 - drag_vector = (0.50, 0.52) - - -class DraggableDungeonList(DraggableList): - teleports: list[OcrResultButton] = [] - navigates: list[OcrResultButton] = [] - - # 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 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=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, MapPlane], - ocr_class=OcrDungeonList, search_button=OCR_DUNGEON_LIST) - - -class DungeonUI(DungeonState): - def dungeon_tab_goto(self, state: DungeonTab): - """ - Args: - state: - - Returns: - bool: If UI switched - - Examples: - self = DungeonUI('alas') - self.device.screenshot() - self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Operation_Briefing) - self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Daily_Training) - self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) - """ - logger.hr('Dungeon tab goto', level=2) - ui_switched = self.ui_ensure(page_guide) - tab_switched = SWITCH_DUNGEON_TAB.set(state, main=self) - - if ui_switched or tab_switched: - if state == KEYWORDS_DUNGEON_TAB.Daily_Training: - logger.info(f'Tab goto {state}, wait until loaded') - self._dungeon_wait_daily_training_loaded() - elif state == KEYWORDS_DUNGEON_TAB.Survival_Index: - logger.info(f'Tab goto {state}, wait until loaded') - self._dungeon_wait_survival_index_loaded() - elif state == KEYWORDS_DUNGEON_TAB.Treasures_Lightward: - logger.info(f'Tab goto {state}, wait until loaded') - self._dungeon_wait_treasures_lightward_loaded() - return True - else: - return False - - def _dungeon_wait_daily_training_loaded(self, skip_first_screenshot=True): - """ - Returns: - bool: True if wait success, False if wait timeout. - - Pages: - in: page_guide, Daily_Training - """ - timeout = Timer(2, count=4).start() - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() - - if timeout.reached(): - logger.warning('Wait daily training loaded timeout') - return False - color = get_color(self.device.image, DAILY_TRAINING_LOADED.area) - if np.mean(color) < 128: - logger.info('Daily training loaded') - return True - - def _dungeon_wait_survival_index_loaded(self, skip_first_screenshot=True): - """ - Returns: - bool: True if wait success, False if wait timeout. - - Pages: - in: page_guide, Survival_Index - """ - timeout = Timer(2, count=4).start() - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() - - if timeout.reached(): - logger.warning('Wait survival index loaded timeout') - return False - if self.appear(SURVIVAL_INDEX_SU_LOADED): - logger.info('Survival index loaded, SURVIVAL_INDEX_SU_LOADED') - return True - if self.appear(SURVIVAL_INDEX_OE_LOADED): - logger.info('Survival index loaded, SURVIVAL_INDEX_OE_LOADED') - return True - - def _dungeon_survival_index_top_appear(self): - if self.appear(SURVIVAL_INDEX_SU_LOADED): - return True - if self.appear(SURVIVAL_INDEX_OE_LOADED): - return True - return False - - def _dungeon_wait_treasures_lightward_loaded(self, skip_first_screenshot=True): - """ - Returns: - bool: True if wait success, False if wait timeout. - - Pages: - 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 - else: - self.device.screenshot() - - if timeout.reached(): - logger.warning('Wait treasures lightward loaded timeout') - return False - if self.appear(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_list_button_has_content(self): - # Check if having any content - # List background: 254, guild border: 225 - r, g, b = cv2.split(self.image_crop(LIST_LOADED_CHECK, copy=False)) - minimum = cv2.min(cv2.min(r, g), b) - minimum = inrange(minimum, lower=0, upper=180) - if minimum.size > 100: - return True - else: - return False - - 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 - - if self._dungeon_list_button_has_content(): - logger.info('Dungeon list loaded') - return True - - def _dungeon_wait_until_echo_or_war_stabled(self, skip_first_screenshot=True): - """ - Returns: - bool: True if wait success, False if wait timeout. - - Pages: - in: page_guide, Survival_Index - """ - # Wait until Forgotten_Hall stabled - timeout = Timer(2, count=4).start() - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() - - # End - if timeout.reached(): - logger.warning('Wait until Echo_of_War stabled timeout') - return False - - DUNGEON_NAV_LIST.load_rows(main=self) - - # End - button = DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Echo_of_War, show_warning=False) - if button: - # 513 is the top of the last row of DungeonNav - if button.area[1] > 513: - logger.info('DungeonNav row Echo_of_War stabled') - return True - else: - logger.info('No Echo_of_War in list skip waiting') - return False - - 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: - nav: - skip_first_screenshot: - """ - logger.hr('Dungeon nav goto', level=2) - logger.info(f'Dungeon nav goto {nav}') - - # Wait rows - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() - DUNGEON_NAV_LIST.load_rows(main=self) - if DUNGEON_NAV_LIST.cur_buttons: - break - - # Wait first row selected - timeout = Timer(0.5, count=2).start() - skip_first_screenshot = True - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() - if timeout.reached(): - logger.info('DUNGEON_NAV_LIST not selected') - break - if button := DUNGEON_NAV_LIST.get_selected_row(main=self): - logger.info(f'DUNGEON_NAV_LIST selected at {button}') - break - - # Check if it's at the first page. - if DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Simulated_Universe, show_warning=False) \ - or DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Ornament_Extraction, show_warning=False): - # Going to use a faster method to navigate but can only start from list top - logger.info('DUNGEON_NAV_LIST at top') - # Update points if possible - # 2.3, No longer weekly points after Divergent Universe unlocked - # if DUNGEON_NAV_LIST.is_row_selected(button, main=self): - # self.dungeon_update_simuni() - # Treasures lightward is always at top - elif DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Forgotten_Hall, show_warning=False) \ - or DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Pure_Fiction, show_warning=False): - logger.info('DUNGEON_NAV_LIST at top') - else: - # To start from any list states. - logger.info('DUNGEON_NAV_LIST not at top') - DUNGEON_NAV_LIST.select_row(nav, main=self) - return True - - # Check the first page - if nav in [ - KEYWORDS_DUNGEON_NAV.Simulated_Universe, - KEYWORDS_DUNGEON_NAV.Divergent_Universe, - KEYWORDS_DUNGEON_NAV.Ornament_Extraction, - KEYWORDS_DUNGEON_NAV.Calyx_Golden, - KEYWORDS_DUNGEON_NAV.Calyx_Crimson, - KEYWORDS_DUNGEON_NAV.Stagnant_Shadow, - KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion, - KEYWORDS_DUNGEON_NAV.Forgotten_Hall, - KEYWORDS_DUNGEON_NAV.Pure_Fiction, - ]: - button = DUNGEON_NAV_LIST.keyword2button(nav) - if button: - DUNGEON_NAV_LIST.select_row(nav, main=self, insight=False) - return True - - # Check the second page - while 1: - 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(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: - in: page_guide, Survival_Index, nav including dungeon - 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) - self.device.click_record_clear() - # Check if dungeon unlocked - for entrance in DUNGEON_LIST.navigates: - entrance: OcrResultButton = entrance - logger.warning(f'Teleport {entrance.matched_keyword} is not unlocked') - if entrance == dungeon: - logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked') - return False - - # Find teleport button - if dungeon not in [tp.matched_keyword for tp in DUNGEON_LIST.teleports]: - # Dungeon name is insight but teleport button is not - logger.info('Dungeon name is insight, swipe down a little bit to find the teleport button') - if dungeon.is_Forgotten_Hall: - DUNGEON_LIST.drag_vector = (-0.4, -0.2) # Keyword loaded is reversed - else: - DUNGEON_LIST.drag_vector = (0.2, 0.4) - DUNGEON_LIST.limit_entrance = True - DUNGEON_LIST.insight_row(dungeon, main=self) - self.device.click_record_clear() - DUNGEON_LIST.drag_vector = DraggableList.drag_vector - DUNGEON_LIST.limit_entrance = False - DUNGEON_LIST.load_rows(main=self) - # Check if dungeon unlocked - for entrance in DUNGEON_LIST.navigates: - if entrance == dungeon: - logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked') - return False - - return True - - def _dungeon_enter(self, dungeon, enter_check_button=COMBAT_PREPARE, skip_first_screenshot=True): - """ - Pages: - in: page_guide, Survival_Index, nav including dungeon - out: COMBAT_PREPARE, FORGOTTEN_HALL_CHECK - """ - logger.hr('Dungeon enter', level=2) - DUNGEON_LIST.use_plane = bool(dungeon.is_Calyx_Crimson) - skip_first_load = skip_first_screenshot - - @run_once - def screenshot_interval_set(): - self.device.screenshot_interval_set('combat') - - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() - - # End - if self.appear(enter_check_button): - logger.info(f'Arrive {enter_check_button.name}') - self.device.screenshot_interval_set() - break - - # Additional - # Popup that confirm character switch - if self.handle_popup_confirm(): - self.interval_reset(page_guide.check_button) - continue - - # Click teleport - if self.appear(page_guide.check_button, interval=1): - if skip_first_load: - skip_first_load = False - else: - DUNGEON_LIST.load_rows(main=self) - entrance = DUNGEON_LIST.keyword2button(dungeon) - if entrance is not None: - self.device.click(entrance) - screenshot_interval_set() - self.interval_reset(page_guide.check_button) - continue - else: - logger.warning(f'Cannot find dungeon entrance of {dungeon}') - continue - - def get_dungeon_interact(self) -> DungeonList | None: - """ - Pages: - in: page_main - """ - if not self.appear(DUNGEON_COMBAT_INTERACT): - logger.info('No dungeon interact') - return None - - self.acquire_lang_checked() - - ocr = OcrDungeonList(DUNGEON_COMBAT_INTERACT_TEXT) - result = ocr.detect_and_ocr(self.device.image) - - dungeon = None - # Special match names in English - # Second row must have at least 3 characters which is the shortest name "Ire" - # Stangnant Shadow: Shape of - # Quanta - if len(result) == 2 and len(result[1].ocr_text) >= 3: - first, second = result[0].ocr_text, result[1].ocr_text - if re.search(r'Stagnant\s*Shadow', first): - dungeon = DungeonList.find_dungeon_by_string(en=second, is_Stagnant_Shadow=True) - elif re.search(r'Cavern\s*of\s*Corrosion', first): - dungeon = DungeonList.find_dungeon_by_string(en=second, is_Cavern_of_Corrosion=True) - elif re.search(r'Echo\s*of\s*War', first): - dungeon = DungeonList.find_dungeon_by_string(en=second, is_Echo_of_War=True) - elif re.search(r'Calyx[\s(]+Golden', first): - dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Golden=True, world=self.plane.world) - elif re.search(r'Calyx[\s(]+Crimson', first): - dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Crimson=True, plane=self.plane) - if dungeon is not None: - logger.attr('DungeonInteract', dungeon) - return dungeon - - # Join - result = ' '.join([row.ocr_text for row in result]) - - # Special match names in Chinese - # Only calyxes need spacial match - if res := re.search(r'(^.+之蕾)', result): - dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Crimson=True, plane=self.plane) - if dungeon is not None: - logger.attr('DungeonInteract', dungeon) - return dungeon - dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Golden=True, world=self.plane.world) - if dungeon is not None: - logger.attr('DungeonInteract', dungeon) - return dungeon - - # Dungeons - try: - dungeon = DungeonList.find(result) - logger.attr('DungeonInteract', dungeon) - return dungeon - except ScriptError: - pass - # Simulated Universe returns Simulated_Universe_World_1 - try: - dungeon = DungeonNav.find(result) - if dungeon == KEYWORDS_DUNGEON_NAV.Simulated_Universe: - dungeon = KEYWORDS_DUNGEON_LIST.Simulated_Universe_World_1 - logger.attr('DungeonInteract', dungeon) - return dungeon - except ScriptError: - pass - # Unknown - logger.attr('DungeonInteract', None) - return None - - def dungeon_goto(self, dungeon: DungeonList): - """ - Returns: - bool: If success - - Pages: - in: page_guide, Survival_Index - out: COMBAT_PREPARE if success - page_guide if failed - - Examples: - from tasks.dungeon.keywords import KEYWORDS_DUNGEON_LIST - self = DungeonUI('src') - self.device.screenshot() - self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) - self.dungeon_goto(KEYWORDS_DUNGEON_LIST.Calyx_Crimson_Harmony) - """ - # Reset search button - DUNGEON_LIST.search_button = OCR_DUNGEON_LIST - - if dungeon.is_Calyx_Crimson \ - or dungeon.is_Stagnant_Shadow \ - or dungeon.is_Cavern_of_Corrosion \ - or dungeon.is_Echo_of_War \ - or dungeon.is_Ornament_Extraction: - 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 - - logger.error(f'Goto dungeon {dungeon} is not supported') - return False diff --git a/tasks/dungeon/ui/interact.py b/tasks/dungeon/ui/interact.py new file mode 100644 index 000000000..89be8ba23 --- /dev/null +++ b/tasks/dungeon/ui/interact.py @@ -0,0 +1,85 @@ +import re + +from module.exception import ScriptError +from module.logger import logger +from tasks.base.ui import UI +from tasks.combat.assets.assets_combat_interact import DUNGEON_COMBAT_INTERACT, DUNGEON_COMBAT_INTERACT_TEXT +from tasks.dungeon.keywords import ( + DungeonList, + DungeonNav, + KEYWORDS_DUNGEON_LIST, + KEYWORDS_DUNGEON_NAV +) +from tasks.dungeon.ui.llist import OcrDungeonName + + +class DungeonUIInteract(UI): + def get_dungeon_interact(self) -> DungeonList | None: + """ + Pages: + in: page_main + """ + if not self.appear(DUNGEON_COMBAT_INTERACT): + logger.info('No dungeon interact') + return None + + self.acquire_lang_checked() + + ocr = OcrDungeonName(DUNGEON_COMBAT_INTERACT_TEXT) + result = ocr.detect_and_ocr(self.device.image) + + dungeon = None + # Special match names in English + # Second row must have at least 3 characters which is the shortest name "Ire" + # Stangnant Shadow: Shape of + # Quanta + if len(result) == 2 and len(result[1].ocr_text) >= 3: + first, second = result[0].ocr_text, result[1].ocr_text + if re.search(r'Stagnant\s*Shadow', first): + dungeon = DungeonList.find_dungeon_by_string(en=second, is_Stagnant_Shadow=True) + elif re.search(r'Cavern\s*of\s*Corrosion', first): + dungeon = DungeonList.find_dungeon_by_string(en=second, is_Cavern_of_Corrosion=True) + elif re.search(r'Echo\s*of\s*War', first): + dungeon = DungeonList.find_dungeon_by_string(en=second, is_Echo_of_War=True) + elif re.search(r'Calyx[\s(]+Golden', first): + dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Golden=True, world=self.plane.world) + elif re.search(r'Calyx[\s(]+Crimson', first): + dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Crimson=True, plane=self.plane) + if dungeon is not None: + logger.attr('DungeonInteract', dungeon) + return dungeon + + # Join + result = ' '.join([row.ocr_text for row in result]) + + # Special match names in Chinese + # Only calyxes need spacial match + if res := re.search(r'(^.+之蕾)', result): + dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Crimson=True, plane=self.plane) + if dungeon is not None: + logger.attr('DungeonInteract', dungeon) + return dungeon + dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Golden=True, world=self.plane.world) + if dungeon is not None: + logger.attr('DungeonInteract', dungeon) + return dungeon + + # Dungeons + try: + dungeon = DungeonList.find(result) + logger.attr('DungeonInteract', dungeon) + return dungeon + except ScriptError: + pass + # Simulated Universe returns Simulated_Universe_World_1 + try: + dungeon = DungeonNav.find(result) + if dungeon == KEYWORDS_DUNGEON_NAV.Simulated_Universe: + dungeon = KEYWORDS_DUNGEON_LIST.Simulated_Universe_World_1 + logger.attr('DungeonInteract', dungeon) + return dungeon + except ScriptError: + pass + # Unknown + logger.attr('DungeonInteract', None) + return None diff --git a/tasks/dungeon/ui/llist.py b/tasks/dungeon/ui/llist.py new file mode 100644 index 000000000..e11e3efe8 --- /dev/null +++ b/tasks/dungeon/ui/llist.py @@ -0,0 +1,398 @@ +import re + +import cv2 +from pponnxcr.predict_system import BoxedResult + +from module.base.base import ModuleBase +from module.base.button import ClickButton +from module.base.decorator import run_once +from module.base.timer import Timer +from module.base.utils import area_center, area_limit, area_offset, crop, image_size +from module.logger import logger +from module.ocr.ocr import Ocr, OcrResultButton +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 +from tasks.base.ui import UI +from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE +from tasks.dungeon.assets.assets_dungeon_ui_list import * +from tasks.dungeon.keywords import ( + DungeonList, + KEYWORDS_DUNGEON_ENTRANCE, + KEYWORDS_DUNGEON_LIST +) +from tasks.dungeon.keywords.classes import DungeonEntrance +from tasks.map.keywords import MapPlane + +LIST_SORTING = Switch('DUNGEON_LIST_SORTING', is_selector=True) +LIST_SORTING.add_state('Ascending', check_button=LIST_ASCENDING) +LIST_SORTING.add_state('Descending', check_button=LIST_DESCENDING) +LIST_SORTING.Ascending = 'Ascending' +LIST_SORTING.Descending = 'Descending' + + +class OcrDungeonName(Ocr): + def after_process(self, result): + # 乙太之蕾•雅利洛-Ⅵ + result = re.sub(r'-[VⅤ][IⅠ]', '-Ⅵ', result) + + # 苏乐达™热砂海选会场 + result = re.sub(r'(苏乐达|蘇樂達|SoulGlad|スラーダ|FelizAlma)[rtT]*M*', r'\1', result) + result = re.sub(r'["\']', '', result) + + result = super().after_process(result) + + if self.lang == 'cn': + result = result.replace('翼', '巽') # 巽风之形 + result = result.replace('皖A0', '50').replace('皖', '') + # 燔灼之形•凝滞虚影 + result = result.replace('熠', '燔') + result = re.sub('^灼之形', '燔灼之形', result) + # 偃偶之形•凝滞虚影 + result = re.sub('^偶之形', '偃偶之形', result) + # 嗔怒之形•凝滞虚影 + result = re.sub('^怒之形', '嗔怒之形', result) + # 蛀星的旧·历战余响 + result = re.sub(r'蛀星的旧.*?历战', '蛀星的旧靥•历战', result) + + # 9支援仓段 + for word in 'Q9α': + result = result.removeprefix(word) + return result + + +class OcrDungeonList(OcrDungeonName): + # Keep __init__ parameter unused + def __init__(self, button: ButtonWrapper = None, lang=None, name=None): + super().__init__(button=button, lang=lang, name='OcrDungeonList') + # target_dungeon: Dungeon attribute to use map planes to predict dungeons only. + self.target_dungeon = None + # limit_entrance: True to ensure the teleport button is insight + self.limit_entrance = False + + def detect_and_ocr(self, image, direct_ocr=False) -> list[BoxedResult]: + if self.button != OCR_DUNGEON_NAME: + if self.limit_entrance: + self.button = ClickButton((*self.button.area[:3], self.button.area[3] - 70)) + return super().detect_and_ocr(image, direct_ocr=direct_ocr) + + # Concat OCR_DUNGEON_NAME and OCR_DUNGEON_TELEPORT + # so they can be OCRed at one time + left = crop(image, OCR_DUNGEON_NAME.area, copy=False) + right = crop(image, OCR_DUNGEON_TELEPORT.area, copy=False) + lw, lh = image_size(left) + rw, rh = image_size(right) + if lh != rh: + logger.error('OCR_DUNGEON_NAME and OCR_DUNGEON_TELEPORT does not have same height, image cannot concat') + image = cv2.hconcat([left, right]) + + if self.limit_entrance: + w, h = image_size(image) + image = crop(image, (0, 0, w, h - 70), copy=False) + + results = super().detect_and_ocr(image, direct_ocr=True) + + # Move box + for result in results: + x, _ = area_center(result.box) + # Belongs to right image + if x >= lw: + result.box = area_offset(result.box, offset=(-lw, 0)) + result.box = area_offset(result.box, offset=OCR_DUNGEON_TELEPORT.area[:2]) + # Belongs to left image + else: + result.box = area_offset(result.box, offset=OCR_DUNGEON_NAME.area[:2]) + + return results + + def _match_result(self, *args, **kwargs): + """ + Convert MapPlane object to their corresponding DungeonList object + """ + matched = super()._match_result(*args, **kwargs) + if self.target_dungeon is not None and matched is not None: + if self.target_dungeon.is_Calyx_Golden: + # convert MapPlane and ignore DungeonList + if isinstance(matched, DungeonList): + return + for dungeon in DungeonList.instances.values(): + if dungeon.is_Calyx_Golden and dungeon.plane == matched: + return dungeon + if self.target_dungeon.is_Calyx_Crimson: + if isinstance(matched, DungeonList): + return + for dungeon in DungeonList.instances.values(): + if dungeon.is_Calyx_Crimson and dungeon.plane == matched: + return dungeon + else: + if isinstance(matched, MapPlane): + return + + return matched + + +class DraggableDungeonList(DraggableList): + teleports: list[OcrResultButton] = [] + navigates: list[OcrResultButton] = [] + + # target_dungeon: Dungeon attribute to use map planes to predict dungeons only. + target_dungeon = None + # 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, -40, 1280, 120) + + def create_ocr_class(*args, **kwargs): + # Passing to OcrDungeonList + obj = OcrDungeonList(*args, **kwargs) + obj.target_dungeon = self.target_dungeon + obj.limit_entrance = self.limit_entrance + return obj + + self.ocr_class = create_ocr_class + 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( + self.cur_buttons, + 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( + self.cur_buttons, + split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Navigate, + relative_area=relative_area + )) + + +DUNGEON_LIST = DraggableDungeonList( + 'DungeonList', keyword_class=[DungeonList, DungeonEntrance, MapPlane], + ocr_class=OcrDungeonList, search_button=OCR_DUNGEON_NAME) + + +class DungeonUIList(UI): + def _dungeon_list_reset(self): + """ + Reset list to top + + Returns: + bool: If success + """ + logger.info('Dungeon list reset') + current = LIST_SORTING.get(main=self) + if current == LIST_SORTING.Descending: + another = LIST_SORTING.Ascending + elif current == LIST_SORTING.Ascending: + another = LIST_SORTING.Descending + else: + logger.warning('Unknown dungeon LIST_SORTING') + return False + + LIST_SORTING.set(another, main=self) + LIST_SORTING.set(current, main=self) + return True + + def _dungeon_insight_index(self, dungeon: DungeonList): + """ + Insight a dungeon using pre-defined dungeon indexes from DUNGEON_LIST + + Pages: + in: page_guide, Survival_Index, nav including dungeon + out: page_guide, Survival_Index, nav including dungeon, dungeon insight + """ + logger.hr('Dungeon insight (index)', level=2) + if dungeon.is_Ornament_Extraction: + # Limit drag area in iOrnament_Extraction + DUNGEON_LIST.search_button = OCR_DUNGEON_NAME_ROGUE + elif dungeon.is_Echo_of_War: + DUNGEON_LIST.search_button = OCR_DUNGEON_LIST + else: + DUNGEON_LIST.search_button = OCR_DUNGEON_NAME + # Predict dungeon by plane name in calyxes where dungeons share the same names + DUNGEON_LIST.target_dungeon = dungeon + DUNGEON_LIST.check_row_order = True + + # Insight dungeon + DUNGEON_LIST.insight_row(dungeon, main=self) + self.device.click_record_clear() + # Check if dungeon unlocked + for entrance in DUNGEON_LIST.navigates: + entrance: OcrResultButton = entrance + logger.warning(f'Teleport {entrance.matched_keyword} is not unlocked') + if entrance == dungeon: + logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked') + return False + + # Find teleport button + if dungeon not in [tp.matched_keyword for tp in DUNGEON_LIST.teleports]: + # Dungeon name is insight but teleport button is not + logger.info('Dungeon name is insight, swipe down a little bit to find the teleport button') + if dungeon.is_Forgotten_Hall: + DUNGEON_LIST.drag_vector = (-0.4, -0.2) # Keyword loaded is reversed + else: + DUNGEON_LIST.drag_vector = (0.2, 0.4) + DUNGEON_LIST.limit_entrance = True + DUNGEON_LIST.insight_row(dungeon, main=self) + self.device.click_record_clear() + DUNGEON_LIST.drag_vector = DraggableList.drag_vector + DUNGEON_LIST.limit_entrance = False + DUNGEON_LIST.load_rows(main=self) + # Check if dungeon unlocked + for entrance in DUNGEON_LIST.navigates: + if entrance.matched_keyword == dungeon: + logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked') + return False + + return True + + def _dungeon_insight_sort(self, dungeon: DungeonList): + """ + Insight a dungeon using sorter and plain drag, reset list on error + """ + logger.hr('Dungeon insight (sort)', level=2) + logger.info(f'Dungeon insight: {dungeon}') + DUNGEON_LIST.search_button = OCR_DUNGEON_NAME + DUNGEON_LIST.target_dungeon = dungeon + DUNGEON_LIST.check_row_order = False + + for _ in range(3): + visited = set() + end_count = 0 + self.device.click_record_clear() + while 1: + visited_count = len(visited) + # Load + DUNGEON_LIST.load_rows(main=self, allow_early_access=True) + for entrance in DUNGEON_LIST.teleports: + if entrance.matched_keyword == dungeon: + logger.info(f'Found dungeon {dungeon}') + return True + for entrance in DUNGEON_LIST.navigates: + if entrance.matched_keyword == dungeon: + logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked') + return False + + # Check end + for entrance in DUNGEON_LIST.cur_buttons: + visited.add(entrance.matched_keyword.name) + if len(visited) <= visited_count: + logger.warning('No more rows loaded') + end_count += 1 + if end_count >= 3: + logger.error('Dungeon list reached end but target dungeon not found') + break + + # Drag down + DUNGEON_LIST.drag_page('down', main=self) + self.wait_until_stable(DUNGEON_LIST.search_button, timer=Timer( + 0, count=0), timeout=Timer(1.5, count=5)) + + self._dungeon_list_reset() + + logger.error('Failed to insight dungeon after 3 trial') + return False + + def dungeon_insight(self, dungeon: DungeonList): + """ + Insight a dungeon + + Pages: + in: page_guide, Survival_Index, nav including dungeon + out: page_guide, Survival_Index, nav including dungeon, dungeon insight + """ + if dungeon.is_Calyx_Crimson or dungeon.is_Stagnant_Shadow: + # Having dungeon sorting and early access + self._dungeon_insight_sort(dungeon) + else: + self._dungeon_insight_index(dungeon) + + def _dungeon_enter(self, dungeon, enter_check_button=COMBAT_PREPARE, skip_first_screenshot=True): + """ + Pages: + in: page_guide, Survival_Index, nav including dungeon + out: COMBAT_PREPARE, FORGOTTEN_HALL_CHECK + """ + logger.hr('Dungeon enter', level=2) + DUNGEON_LIST.target_dungeon = dungeon + skip_first_load = skip_first_screenshot + + @run_once + def screenshot_interval_set(): + self.device.screenshot_interval_set('combat') + + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.appear(enter_check_button): + logger.info(f'Arrive {enter_check_button.name}') + break + + # Additional + # Popup that confirm character switch + if self.handle_popup_confirm(): + self.interval_reset(page_guide.check_button) + continue + + # Click teleport + if self.appear(page_guide.check_button, interval=1): + if skip_first_load: + skip_first_load = False + else: + DUNGEON_LIST.load_rows(main=self) + entrance = DUNGEON_LIST.keyword2button(dungeon) + if entrance is not None: + # Avoid clicking the soring button + entrance.button = area_limit(entrance.button, OCR_DUNGEON_TELEPORT.area) + self.device.click(entrance) + screenshot_interval_set() + self.interval_reset(page_guide.check_button) + continue + else: + logger.warning(f'Cannot find dungeon entrance of {dungeon}') + continue + + self.device.screenshot_interval_set() + + +if __name__ == '__main__': + self = DungeonUIList('src') + self.device.screenshot() + self.dungeon_insight(KEYWORDS_DUNGEON_LIST.Echo_of_War_Divine_Seed) diff --git a/tasks/dungeon/ui/nav.py b/tasks/dungeon/ui/nav.py new file mode 100644 index 000000000..c173bb883 --- /dev/null +++ b/tasks/dungeon/ui/nav.py @@ -0,0 +1,351 @@ +import cv2 +import numpy as np + +from module.base.base import ModuleBase +from module.base.timer import Timer +from module.base.utils import get_color +from module.logger import logger +from module.ocr.ocr import Ocr +from module.ui.draggable_list import DraggableList +from module.ui.switch import Switch +from tasks.base.page import page_guide +from tasks.base.ui import UI +from tasks.dungeon.assets.assets_dungeon_ui import * +from tasks.dungeon.assets.assets_dungeon_ui_rogue import * +from tasks.dungeon.keywords import ( + DungeonNav, + DungeonTab, + KEYWORDS_DUNGEON_NAV, + KEYWORDS_DUNGEON_TAB +) +from tasks.map.interact.aim import inrange + + +class DungeonTabSwitch(Switch): + SEARCH_BUTTON = TAB_SEARCH + + def add_state(self, state, check_button, click_button=None): + # Load search + if check_button is not None: + check_button.load_search(self.__class__.SEARCH_BUTTON.area) + if click_button is not None: + click_button.load_search(self.__class__.SEARCH_BUTTON.area) + return super().add_state(state, check_button, click_button) + + def click(self, state, main): + """ + Args: + state (str): + main (ModuleBase): + """ + button = self.get_data(state)['click_button'] + _ = main.appear(button) # Search button to load offset + main.device.click(button) + + +SWITCH_DUNGEON_TAB = DungeonTabSwitch('DungeonTab', is_selector=True) +SWITCH_DUNGEON_TAB.add_state( + KEYWORDS_DUNGEON_TAB.Operation_Briefing, + check_button=OPERATION_BRIEFING_CHECK, + click_button=OPERATION_BRIEFING_CLICK +) +SWITCH_DUNGEON_TAB.add_state( + KEYWORDS_DUNGEON_TAB.Daily_Training, + check_button=DAILY_TRAINING_CHECK, + click_button=DAILY_TRAINING_CLICK +) +SWITCH_DUNGEON_TAB.add_state( + KEYWORDS_DUNGEON_TAB.Survival_Index, + check_button=SURVIVAL_INDEX_CHECK, + click_button=SURVIVAL_INDEX_CLICK +) +SWITCH_DUNGEON_TAB.add_state( + KEYWORDS_DUNGEON_TAB.Simulated_Universe, + check_button=SIMULATED_UNIVERSE_CHECK, + click_button=SIMULATED_UNIVERSE_CLICK +) +SWITCH_DUNGEON_TAB.add_state( + KEYWORDS_DUNGEON_TAB.Treasures_Lightward, + check_button=TREASURES_LIGHTWARD_CHECK, + click_button=TREASURES_LIGHTWARD_CLICK +) + + +class OcrDungeonNav(Ocr): + def after_process(self, result): + result = super().after_process(result) + result = result.replace('#', '') + if self.lang == 'cn': + result = result.replace('萼喜', '萼') + result = result.replace('带', '滞') # 凝带虚影 + return result + + +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 + drag_vector = (0.50, 0.52) + + +DUNGEON_NAV_LIST = DraggableDungeonNav( + 'DungeonNavList', keyword_class=DungeonNav, ocr_class=OcrDungeonNav, search_button=OCR_DUNGEON_NAV) + + +class DungeonUINav(UI): + def dungeon_tab_goto(self, state: DungeonTab): + """ + Args: + state: + + Returns: + bool: If UI switched + + Examples: + self = DungeonUI('alas') + self.device.screenshot() + self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Operation_Briefing) + self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Daily_Training) + self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) + """ + logger.hr('Dungeon tab goto', level=2) + ui_switched = self.ui_ensure(page_guide) + tab_switched = SWITCH_DUNGEON_TAB.set(state, main=self) + + if ui_switched or tab_switched: + if state == KEYWORDS_DUNGEON_TAB.Daily_Training: + logger.info(f'Tab goto {state}, wait until loaded') + self._dungeon_wait_daily_training_loaded() + elif state == KEYWORDS_DUNGEON_TAB.Survival_Index: + logger.info(f'Tab goto {state}, wait until loaded') + self._dungeon_wait_survival_index_loaded() + elif state == KEYWORDS_DUNGEON_TAB.Treasures_Lightward: + logger.info(f'Tab goto {state}, wait until loaded') + self._dungeon_wait_treasures_lightward_loaded() + return True + else: + return False + + def _dungeon_wait_daily_training_loaded(self, skip_first_screenshot=True): + """ + Returns: + bool: True if wait success, False if wait timeout. + + Pages: + in: page_guide, Daily_Training + """ + timeout = Timer(2, count=4).start() + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + if timeout.reached(): + logger.warning('Wait daily training loaded timeout') + return False + color = get_color(self.device.image, DAILY_TRAINING_LOADED.area) + if np.mean(color) < 128: + logger.info('Daily training loaded') + return True + + def _dungeon_wait_survival_index_loaded(self, skip_first_screenshot=True): + """ + Returns: + bool: True if wait success, False if wait timeout. + + Pages: + in: page_guide, Survival_Index + """ + timeout = Timer(2, count=4).start() + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + if timeout.reached(): + logger.warning('Wait survival index loaded timeout') + return False + if self.appear(SURVIVAL_INDEX_SU_LOADED): + logger.info('Survival index loaded, SURVIVAL_INDEX_SU_LOADED') + return True + if self.appear(SURVIVAL_INDEX_OE_LOADED): + logger.info('Survival index loaded, SURVIVAL_INDEX_OE_LOADED') + return True + + def _dungeon_survival_index_top_appear(self): + if self.appear(SURVIVAL_INDEX_SU_LOADED): + return True + if self.appear(SURVIVAL_INDEX_OE_LOADED): + return True + return False + + def _dungeon_wait_treasures_lightward_loaded(self, skip_first_screenshot=True): + """ + Returns: + bool: True if wait success, False if wait timeout. + + Pages: + 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 + else: + self.device.screenshot() + + if timeout.reached(): + logger.warning('Wait treasures lightward loaded timeout') + return False + if self.appear(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_list_button_has_content(self): + # Check if having any content + # List background: 254, guild border: 225 + r, g, b = cv2.split(self.image_crop(LIST_LOADED_CHECK, copy=False)) + minimum = cv2.min(cv2.min(r, g), b) + minimum = inrange(minimum, lower=0, upper=180) + if minimum.size > 100: + return True + else: + return False + + 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 + + if self._dungeon_list_button_has_content(): + logger.info('Dungeon list loaded') + return True + + def _dungeon_wait_until_echo_or_war_stabled(self, skip_first_screenshot=True): + """ + Returns: + bool: True if wait success, False if wait timeout. + + Pages: + in: page_guide, Survival_Index + """ + # Wait until Forgotten_Hall stabled + timeout = Timer(2, count=4).start() + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if timeout.reached(): + logger.warning('Wait until Echo_of_War stabled timeout') + return False + + DUNGEON_NAV_LIST.load_rows(main=self) + + # End + button = DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Echo_of_War, show_warning=False) + if button: + # 513 is the top of the last row of DungeonNav + if button.area[1] > 513: + logger.info('DungeonNav row Echo_of_War stabled') + return True + else: + logger.info('No Echo_of_War in list skip waiting') + return False + + 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: + nav: + skip_first_screenshot: + """ + logger.hr('Dungeon nav goto', level=2) + logger.info(f'Dungeon nav goto {nav}') + + # Wait rows + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + DUNGEON_NAV_LIST.load_rows(main=self) + if DUNGEON_NAV_LIST.cur_buttons: + break + + # Wait first row selected + timeout = Timer(0.5, count=2).start() + skip_first_screenshot = True + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + if timeout.reached(): + logger.info('DUNGEON_NAV_LIST not selected') + break + if button := DUNGEON_NAV_LIST.get_selected_row(main=self): + logger.info(f'DUNGEON_NAV_LIST selected at {button}') + break + + # Check if it's at the first page. + if DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Simulated_Universe, show_warning=False) \ + or DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Ornament_Extraction, show_warning=False): + # Going to use a faster method to navigate but can only start from list top + logger.info('DUNGEON_NAV_LIST at top') + # Update points if possible + # 2.3, No longer weekly points after Divergent Universe unlocked + # if DUNGEON_NAV_LIST.is_row_selected(button, main=self): + # self.dungeon_update_simuni() + # Treasures lightward is always at top + elif DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Forgotten_Hall, show_warning=False) \ + or DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Pure_Fiction, show_warning=False): + logger.info('DUNGEON_NAV_LIST at top') + else: + # To start from any list states. + logger.info('DUNGEON_NAV_LIST not at top') + DUNGEON_NAV_LIST.select_row(nav, main=self) + return True + + # Check the first page + if nav in [ + KEYWORDS_DUNGEON_NAV.Simulated_Universe, + KEYWORDS_DUNGEON_NAV.Divergent_Universe, + KEYWORDS_DUNGEON_NAV.Ornament_Extraction, + KEYWORDS_DUNGEON_NAV.Calyx_Golden, + KEYWORDS_DUNGEON_NAV.Calyx_Crimson, + KEYWORDS_DUNGEON_NAV.Stagnant_Shadow, + KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion, + KEYWORDS_DUNGEON_NAV.Forgotten_Hall, + KEYWORDS_DUNGEON_NAV.Pure_Fiction, + ]: + button = DUNGEON_NAV_LIST.keyword2button(nav) + if button: + DUNGEON_NAV_LIST.select_row(nav, main=self, insight=False) + return True + + # Check the second page + while 1: + 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(nav, main=self, insight=False) + return True diff --git a/tasks/dungeon/state.py b/tasks/dungeon/ui/state.py similarity index 100% rename from tasks/dungeon/state.py rename to tasks/dungeon/ui/state.py diff --git a/tasks/dungeon/ui/ui.py b/tasks/dungeon/ui/ui.py new file mode 100644 index 000000000..ad9c4042a --- /dev/null +++ b/tasks/dungeon/ui/ui.py @@ -0,0 +1,41 @@ +from module.logger import logger +from tasks.dungeon.keywords import DungeonList +from tasks.dungeon.ui.interact import DungeonUIInteract +from tasks.dungeon.ui.llist import DungeonUIList +from tasks.dungeon.ui.nav import DungeonUINav +from tasks.dungeon.ui.state import DungeonState + + +class DungeonUI(DungeonState, DungeonUINav, DungeonUIList, DungeonUIInteract): + def dungeon_goto(self, dungeon: DungeonList): + """ + Returns: + bool: If success + + Pages: + in: page_guide, Survival_Index + out: COMBAT_PREPARE if success + page_guide if failed + + Examples: + from tasks.dungeon.keywords import KEYWORDS_DUNGEON_LIST + self = DungeonUI('src') + self.device.screenshot() + self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) + self.dungeon_goto(KEYWORDS_DUNGEON_LIST.Calyx_Crimson_Harmony) + """ + # Reset search button + if dungeon.is_Calyx_Golden \ + or dungeon.is_Calyx_Crimson \ + or dungeon.is_Stagnant_Shadow \ + or dungeon.is_Cavern_of_Corrosion \ + or dungeon.is_Echo_of_War \ + or dungeon.is_Ornament_Extraction: + self.dungeon_nav_goto(dungeon.dungeon_nav) + self._dungeon_wait_until_dungeon_list_loaded() + self.dungeon_insight(dungeon) + self._dungeon_enter(dungeon) + return True + + logger.error(f'Goto dungeon {dungeon} is not supported') + return False diff --git a/tasks/dungeon/ui_rogue.py b/tasks/dungeon/ui/ui_rogue.py similarity index 93% rename from tasks/dungeon/ui_rogue.py rename to tasks/dungeon/ui/ui_rogue.py index 1d2304115..a73968cf5 100644 --- a/tasks/dungeon/ui_rogue.py +++ b/tasks/dungeon/ui/ui_rogue.py @@ -3,9 +3,11 @@ from module.base.utils import random_rectangle_vector from module.logger import logger from tasks.base.page import page_guide from tasks.dungeon.assets.assets_dungeon_ui import * +from tasks.dungeon.assets.assets_dungeon_ui_list import OCR_DUNGEON_LIST from tasks.dungeon.assets.assets_dungeon_ui_rogue import * from tasks.dungeon.keywords import KEYWORDS_DUNGEON_NAV, KEYWORDS_DUNGEON_TAB -from tasks.dungeon.ui import DungeonUI, SWITCH_DUNGEON_TAB +from tasks.dungeon.ui.nav import SWITCH_DUNGEON_TAB +from tasks.dungeon.ui.ui import DungeonUI from tasks.forgotten_hall.assets.assets_forgotten_hall_ui import TELEPORT @@ -41,7 +43,7 @@ class DungeonRogueUI(DungeonUI): logger.info(f'Tab goto {state}, wait until loaded') self._dungeon_wait_until_rogue_loaded() # Switch nav - self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Simulated_Universe) + self.dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Simulated_Universe) # No idea how to wait list loaded # List is not able to swipe without fully loaded self.wait_until_stable(LIST_LOADED_CHECK) @@ -59,7 +61,7 @@ class DungeonRogueUI(DungeonUI): if self.appear(SURVIVAL_INDEX_SU_LOADED): logger.info('Already at nav Simulated_Universe') else: - self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Simulated_Universe) + self.dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Simulated_Universe) def _dungeon_wait_until_rogue_loaded(self, skip_first_screenshot=True): """ diff --git a/tasks/dungeon/weekly.py b/tasks/dungeon/weekly.py index 1fb29992e..616035a23 100644 --- a/tasks/dungeon/weekly.py +++ b/tasks/dungeon/weekly.py @@ -2,10 +2,9 @@ from module.config.utils import get_server_next_monday_update from module.logger import logger 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.assets.assets_dungeon_ui import OCR_WEEKLY_LIMIT from tasks.dungeon.dungeon import Dungeon from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_NAV, KEYWORDS_DUNGEON_TAB -from tasks.dungeon.ui import DUNGEON_LIST class OcrWeeklyLimit(DigitCounter): @@ -78,8 +77,7 @@ class WeeklyDungeon(Dungeon): # UI switches 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(KEYWORDS_DUNGEON_NAV.Echo_of_War) + self.dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Echo_of_War) self._dungeon_wait_until_dungeon_list_loaded() monday = get_server_next_monday_update(self.config.Scheduler_ServerUpdate) @@ -94,7 +92,7 @@ class WeeklyDungeon(Dungeon): self.config.task_delay(target=monday) self.config.task_stop() - self._dungeon_insight(dungeon) + self.dungeon_insight(dungeon) self._dungeon_enter(dungeon) # Combat diff --git a/tasks/forgotten_hall/ui.py b/tasks/forgotten_hall/ui.py index 08b1aa7a8..98dfc1a91 100644 --- a/tasks/forgotten_hall/ui.py +++ b/tasks/forgotten_hall/ui.py @@ -10,8 +10,8 @@ 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.ui.ui import DungeonUI 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 @@ -187,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(KEYWORDS_DUNGEON_NAV.Forgotten_Hall) + 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/map/keywords/plane.py b/tasks/map/keywords/plane.py index cd478717b..fe324b436 100644 --- a/tasks/map/keywords/plane.py +++ b/tasks/map/keywords/plane.py @@ -465,8 +465,19 @@ Luofu_TheShacklingPrison = MapPlane( world_id=2, plane_id=2024101, ) -Penacony_TheReverieReality = MapPlane( +Luofu_Skysplitter = MapPlane( id=43, + name='Luofu_Skysplitter', + cn='竞锋舰', + cht='競鋒艦', + en='Skysplitter', + jp='競鋒艦', + es='Bifurcacielos', + world_id=2, + plane_id=2024201, +) +Penacony_TheReverieReality = MapPlane( + id=44, name='Penacony_TheReverieReality', cn='「白日梦」酒店-现实', cht='「白日夢」飯店-現實', @@ -477,7 +488,7 @@ Penacony_TheReverieReality = MapPlane( plane_id=1030501, ) Penacony_GoldenHour = MapPlane( - id=44, + id=45, name='Penacony_GoldenHour', cn='黄金的时刻', cht='黃金的時刻', @@ -488,7 +499,7 @@ Penacony_GoldenHour = MapPlane( plane_id=1030101, ) Penacony_DreamEdge = MapPlane( - id=45, + id=46, name='Penacony_DreamEdge', cn='筑梦边境', cht='築夢邊境', @@ -499,7 +510,7 @@ Penacony_DreamEdge = MapPlane( plane_id=2031301, ) Penacony_AChildDream = MapPlane( - id=46, + id=47, name='Penacony_AChildDream', cn='稚子的梦', cht='稚子的夢', @@ -510,7 +521,7 @@ Penacony_AChildDream = MapPlane( plane_id=2031201, ) Penacony_TheReverieDreamscape = MapPlane( - id=47, + id=48, name='Penacony_TheReverieDreamscape', cn='「白日梦」酒店-梦境', cht='「白日夢」飯店-夢境', @@ -521,7 +532,7 @@ Penacony_TheReverieDreamscape = MapPlane( plane_id=2031101, ) Penacony_DewlightPavilion = MapPlane( - id=48, + id=49, name='Penacony_DewlightPavilion', cn='朝露公馆', cht='朝露公館', @@ -532,7 +543,7 @@ Penacony_DewlightPavilion = MapPlane( plane_id=2032201, ) Penacony_ClockStudiosThemePark = MapPlane( - id=49, + id=50, name='Penacony_ClockStudiosThemePark', cn='克劳克影视乐园', cht='克勞克影視樂園', @@ -543,7 +554,7 @@ Penacony_ClockStudiosThemePark = MapPlane( plane_id=2032101, ) Penacony_DreamfluxReef = MapPlane( - id=50, + id=51, name='Penacony_DreamfluxReef', cn='流梦礁', cht='流夢礁', @@ -554,7 +565,7 @@ Penacony_DreamfluxReef = MapPlane( plane_id=1030401, ) Penacony_SoulGladScorchsandAuditionVenue = MapPlane( - id=51, + id=52, name='Penacony_SoulGladScorchsandAuditionVenue', cn='苏乐达热砂海选会场', cht='蘇樂達熱砂海選會場', @@ -565,7 +576,7 @@ Penacony_SoulGladScorchsandAuditionVenue = MapPlane( plane_id=2033101, ) Penacony_PenaconyGrandTheater = MapPlane( - id=52, + id=53, name='Penacony_PenaconyGrandTheater', cn='匹诺康尼大剧院', cht='匹諾康尼大劇院', diff --git a/tasks/ornament/combat.py b/tasks/ornament/combat.py index c1c6c730c..5d880ea2d 100644 --- a/tasks/ornament/combat.py +++ b/tasks/ornament/combat.py @@ -6,7 +6,7 @@ from tasks.base.assets.assets_base_popup import POPUP_CANCEL from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_LIST from tasks.dungeon.dungeon import Dungeon -from tasks.dungeon.state import DungeonState +from tasks.dungeon.ui.state import DungeonState from tasks.map.route.loader import RouteLoader from tasks.map.route.route.daily import OrnamentExtraction__route from tasks.ornament.assets.assets_ornament_combat import * diff --git a/tasks/planner/keywords/item_ascension.py b/tasks/planner/keywords/item_ascension.py index 5bd00204b..bb7fe6d8e 100644 --- a/tasks/planner/keywords/item_ascension.py +++ b/tasks/planner/keywords/item_ascension.py @@ -224,8 +224,34 @@ Dream_Fridge = ItemAscension( item_group=1100, dungeon_id=1115, ) -Dream_Flamer = ItemAscension( +Nail_of_the_Beast_Coffin = ItemAscension( id=18, + name='Nail_of_the_Beast_Coffin', + cn='兽棺之钉', + cht='獸棺之釘', + en='Nail of the Beast Coffin', + jp='獣棺の釘', + es='Clavo del ataúd bestial', + rarity='VeryRare', + item_id=110424, + item_group=1100, + dungeon_id=1120, +) +A_Glass_of_the_Besotted_Era = ItemAscension( + id=19, + name='A_Glass_of_the_Besotted_Era', + cn='一杯酩酊的时代', + cht='一杯酩酊的時代', + en='A Glass of the Besotted Era', + jp='酩酊する時代の一杯', + es='Copa de la era embriagada', + rarity='VeryRare', + item_id=110425, + item_group=1100, + dungeon_id=1121, +) +Dream_Flamer = ItemAscension( + id=20, name='Dream_Flamer', cn='炙梦喷枪', cht='炙夢噴槍', diff --git a/tasks/planner/keywords/item_weekly.py b/tasks/planner/keywords/item_weekly.py index 7e8c35f5c..e9b554687 100644 --- a/tasks/planner/keywords/item_weekly.py +++ b/tasks/planner/keywords/item_weekly.py @@ -81,3 +81,16 @@ Lost_Echo_of_the_Shared_Wish = ItemWeekly( item_group=1310, dungeon_id=1305, ) +Auspice_Sliver = ItemWeekly( + id=7, + name='Auspice_Sliver', + cn='吉光片羽', + cht='吉光片羽', + en='Auspice Sliver', + jp='吉光の羽', + es='Pluma auspiciosa', + rarity='VeryRare', + item_id=110506, + item_group=1310, + dungeon_id=1306, +) diff --git a/tasks/planner/scan.py b/tasks/planner/scan.py index 76b1212a6..7919f72c2 100644 --- a/tasks/planner/scan.py +++ b/tasks/planner/scan.py @@ -37,6 +37,8 @@ class OcrItemName(Ocr): # Error words on blank background result = re.sub('^[國東]', '', result) result = re.sub('時$', '', result) + # 一杯酩酊的时代 + result = re.sub('一杯[酪酩酊酐]*的', '一杯酩酊的', result) return result diff --git a/tasks/rogue/entry/entry.py b/tasks/rogue/entry/entry.py index 6a94b51b9..f18019b24 100644 --- a/tasks/rogue/entry/entry.py +++ b/tasks/rogue/entry/entry.py @@ -14,8 +14,8 @@ from tasks.base.assets.assets_base_page import MAP_EXIT from tasks.base.page import page_guide, page_item, page_main, page_rogue from tasks.dungeon.keywords import DungeonList from tasks.dungeon.keywords.dungeon import Simulated_Universe_World_1 -from tasks.dungeon.state import OcrSimUniPoint -from tasks.dungeon.ui_rogue import DungeonRogueUI +from tasks.dungeon.ui.state import OcrSimUniPoint +from tasks.dungeon.ui.ui_rogue import DungeonRogueUI from tasks.forgotten_hall.assets.assets_forgotten_hall_ui import TELEPORT from tasks.rogue.assets.assets_rogue_entry import ( LEVEL_CONFIRM, diff --git a/tasks/rogue/event/preset.py b/tasks/rogue/event/preset.py index e6387b591..5bc17f567 100644 --- a/tasks/rogue/event/preset.py +++ b/tasks/rogue/event/preset.py @@ -123,8 +123,8 @@ STRATEGY_COMMON = { KEYWORDS_ROGUE_EVENT_OPTION.Leave_3c49 ], KEYWORDS_ROGUE_EVENT_TITLE.Robot_Sales_Terminal: [ - KEYWORDS_ROGUE_EVENT_OPTION.Purchase_a_1_3_star_Blessing, - KEYWORDS_ROGUE_EVENT_OPTION.Purchase_a_1_2_star_Blessing, + KEYWORDS_ROGUE_EVENT_OPTION.Purchase_1_Blessing_of_1_to_3_star_rarity, + KEYWORDS_ROGUE_EVENT_OPTION.Purchase_1_Blessing_of_1_to_3_star_rarity, KEYWORDS_ROGUE_EVENT_OPTION.Leave_3c49 ], KEYWORDS_ROGUE_EVENT_TITLE.History_Fictionologists: [ diff --git a/tasks/rogue/event/reward.py b/tasks/rogue/event/reward.py index a280c24ad..b7937005f 100644 --- a/tasks/rogue/event/reward.py +++ b/tasks/rogue/event/reward.py @@ -4,7 +4,7 @@ from module.base.timer import Timer from module.logger import logger from tasks.base.assets.assets_base_popup import GET_REWARD from tasks.combat.interact import CombatInteract -from tasks.dungeon.state import DungeonState +from tasks.dungeon.ui.state import DungeonState from tasks.rogue.assets.assets_rogue_reward import REWARD_CLOSE, USE_IMMERSIFIER, USE_STAMINA from tasks.rogue.blessing.ui import RogueUI diff --git a/tasks/rogue/keywords/bonus.py b/tasks/rogue/keywords/bonus.py index f3f5be344..a9ac05127 100644 --- a/tasks/rogue/keywords/bonus.py +++ b/tasks/rogue/keywords/bonus.py @@ -75,32 +75,32 @@ Equilibrium_Universe = RogueBonus( jp='均衡な宇宙', es='Universo equilibrado', ) -Path_of_Preservation = RogueBonus( +Mechanic = RogueBonus( id=9, - name='Path_of_Preservation', - cn='存护之路', - cht='存護之路', - en='Path of Preservation', - jp='存護の道', - es='Camino de la Conservación', + name='Mechanic', + cn='机修工', + cht='機修工', + en='Mechanic', + jp='機械修理工', + es='Mecánic', ) -Path_of_Remembrance = RogueBonus( +Surveyor = RogueBonus( id=10, - name='Path_of_Remembrance', - cn='记忆之路', - cht='記憶之路', - en='Path of Remembrance', - jp='記憶の道', - es='Camino de la Reminiscencia', + name='Surveyor', + cn='测绘师', + cht='測繪師', + en='Surveyor', + jp='測量士', + es='Topógraf', ) -Path_of_Nihility = RogueBonus( +Adventurer = RogueBonus( id=11, - name='Path_of_Nihility', - cn='虚无之路', - cht='虛無之路', - en='Path of Nihility', - jp='虚無の道', - es='Camino de la Nihilidad', + name='Adventurer', + cn='冒险家', + cht='冒險家', + en='Adventurer', + jp='冒険家', + es='Aventurero', ) Path_of_Abundance = RogueBonus( id=12, @@ -246,3 +246,39 @@ Lying_Cap = RogueBonus( jp='ペテンハット', es='Sombrero mentiroso', ) +Case_Folder = RogueBonus( + id=28, + name='Case_Folder', + cn='案件簿', + cht='案件簿', + en='Case Folder', + jp='事件簿', + es='Expediente de casos', +) +Bloodguilt_Tome = RogueBonus( + id=29, + name='Bloodguilt_Tome', + cn='血罪书', + cht='血罪書', + en='Bloodguilt Tome', + jp='血罪書', + es='Tomo de la culpa sangrienta', +) +Shuttle_Boat = RogueBonus( + id=30, + name='Shuttle_Boat', + cn='梭子船', + cht='渡船', + en='Shuttle Boat', + jp='杼船', + es='Nave lanzadera', +) +Consciousness_Cluster = RogueBonus( + id=31, + name='Consciousness_Cluster', + cn='意识群', + cht='意識群', + en='Consciousness Cluster', + jp='意識群', + es='Grupo de conciencia', +) diff --git a/tasks/rogue/keywords/event_option.py b/tasks/rogue/keywords/event_option.py index 64808b8fe..ac31eb358 100644 --- a/tasks/rogue/keywords/event_option.py +++ b/tasks/rogue/keywords/event_option.py @@ -1218,21 +1218,21 @@ Let_the_sleeping_soldiers_wake_up_again = RogueEventOption( jp='熟睡する兵士を「再び目覚めさせる」', es='Dejas que los soldados dormidos despierten nuevamente.', ) -Purchase_a_1_2_star_Blessing = RogueEventOption( +Purchase_1_Blessing_of_1_to_2_star_rarity = RogueEventOption( id=136, - name='Purchase_a_1_2_star_Blessing', + name='Purchase_1_Blessing_of_1_to_2_star_rarity', cn='购买1个1-2星祝福', cht='購買1個一至二星祝福', - en='Purchase a 1–2 star Blessing', + en='Purchase 1 Blessing of 1- to 2-star rarity', jp='★1~2の祝福を1個購入する', es='Compra 1 bendición de 1-2 estrellas.', ) -Purchase_a_1_3_star_Blessing = RogueEventOption( +Purchase_1_Blessing_of_1_to_3_star_rarity = RogueEventOption( id=137, - name='Purchase_a_1_3_star_Blessing', + name='Purchase_1_Blessing_of_1_to_3_star_rarity', cn='购买1个1-3星祝福', cht='購買1個一至三星祝福', - en='Purchase a 1-3 star Blessing', + en='Purchase 1 Blessing of 1- to 3-star rarity', jp='★1~3の祝福を1個購入する', es='Compra 1 bendición de 1-3 estrellas.', ) @@ -2892,12 +2892,12 @@ Charge_head_on = RogueEventOption( jp='正面から突入する!', es='¡A la carga de frente!', ) -It_is_an_all_or_nothing_move = RogueEventOption( +It_is_a_daring_move_that_risks_it_all = RogueEventOption( id=322, - name='It_is_an_all_or_nothing_move', + name='It_is_a_daring_move_that_risks_it_all', cn='这是一场孤注一掷的行动。', cht='這是一場孤注一擲的行動。', - en='It is an all-or-nothing move.', + en='It is a daring move that risks it all.', jp='これは一か八かの作戦だ', es='Es una acción desesperada.', ) @@ -3549,3 +3549,723 @@ Increase_experimental_samples = RogueEventOption( jp='実験サンプルを増やす。', es='Aumentas las muestras experimentales.', ) +The_vending_machine_displays_a_discount = RogueEventOption( + id=395, + name='The_vending_machine_displays_a_discount', + cn='售货机亮出了折扣。', + cht='販賣機亮出了折扣。', + en='The vending machine displays a discount.', + jp='自動販売機が割引と表示した', + es='La máquina expendedora muestra un descuento.', +) +It_too_expensive = RogueEventOption( + id=396, + name='It_too_expensive', + cn='太贵了。', + cht='太貴了。', + en="It's too expensive.", + jp='高すぎる', + es='Es muy caro.', +) +The_vending_machine_displays_the_price = RogueEventOption( + id=397, + name='The_vending_machine_displays_the_price', + cn='售货机亮出了售价。', + cht='販賣機亮出了售價。', + en='The vending machine displays the price.', + jp='自動販売機が販売価格を表示した', + es='La máquina expendedora muestra el precio.', +) +I_want_freebies = RogueEventOption( + id=398, + name='I_want_freebies', + cn='我要免费的!', + cht='我要免費的!', + en='I want freebies!', + jp='無料がいい!', + es='¡Quiero cosas gratis!', +) +You_better_reconsider = RogueEventOption( + id=399, + name='You_better_reconsider', + cn='你最好再想想。', + cht='你最好再想想。', + en='You better reconsider.', + jp='考え直したほうがいい', + es='Será mejor que lo reconsideres.', +) +Is_this_enough = RogueEventOption( + id=400, + name='Is_this_enough', + cn='这个够了吗?', + cht='這個夠了嗎?', + en='Is this enough?', + jp='これでいい?', + es='¿Acaso es suficiente?', +) +Do_me_a_favor = RogueEventOption( + id=401, + name='Do_me_a_favor', + cn='给我个面子。', + cht='給我一個面子。', + en='Do me a favor.', + jp='顔を立ててほしい', + es='Hazme un favor.', +) +The_vending_machine_spits_out_the_product = RogueEventOption( + id=402, + name='The_vending_machine_spits_out_the_product', + cn='售货机吐出了商品。', + cht='販賣機吐出了商品。', + en='The vending machine spits out the product.', + jp='自動販売機が商品を吐き出した', + es='La máquina expendedora escupe el producto.', +) +Show_it_how_strong_you_are = RogueEventOption( + id=403, + name='Show_it_how_strong_you_are', + cn='让它看看你有多强。', + cht='讓它看看你有多強。', + en='Show it how strong you are.', + jp='強さを見せつける', + es='Demuéstrale lo fuerte que eres.', +) +Can_t_beat_it_Time_to_run = RogueEventOption( + id=404, + name='Can_t_beat_it_Time_to_run', + cn='打不过,溜了溜了。', + cht='打不過,溜了溜了。', + en="Can't beat it. Time to run!", + jp='勝てないから逃げる', + es='Si no puedes con él, sal pitando.', +) +Listen_to_him_speak = RogueEventOption( + id=405, + name='Listen_to_him_speak', + cn='听他说下去。', + cht='聽他說下去。', + en='Listen to him speak.', + jp='彼の話を聞き続ける', + es='Escucha lo que dice.', +) +Leave_after_tasting = RogueEventOption( + id=406, + name='Leave_after_tasting', + cn='试吃后离开。', + cht='試吃後離開。', + en='Leave after tasting.', + jp='試食して立ち去る', + es='Vete después de probarlo.', +) +Is_there_anything_else = RogueEventOption( + id=407, + name='Is_there_anything_else', + cn='还有别的吗?', + cht='還有別的嗎?', + en='Is there anything else?', + jp='まだ他に何かある?', + es='¿Hay algo más?', +) +Take_away_the_sample_testers = RogueEventOption( + id=408, + name='Take_away_the_sample_testers', + cn='带走试吃品。', + cht='帶走試吃品。', + en='Take away the sample testers.', + jp='試食品を持ち帰る', + es='Llévate las muestras.', +) +I_wanna_buy_em_all = RogueEventOption( + id=409, + name='I_wanna_buy_em_all', + cn='我全买了!', + cht='我全買了!', + en="I wanna buy em' all!", + jp='全部もらう!', + es='¡Quiero comprarlos todos!', +) +Stop_his_imperial_worshiping_behavior = RogueEventOption( + id=410, + name='Stop_his_imperial_worshiping_behavior', + cn='制止他的帝国崇拜行为。', + cht='制止他的帝國崇拜行為。', + en='Stop his imperial worshiping behavior.', + jp='帝国を崇拝する彼の行為を止める', + es='Detén su comportamiento de adoración imperialista.', +) +Find_a_excuse_and_leave_this_place = RogueEventOption( + id=411, + name='Find_a_excuse_and_leave_this_place', + cn='找借口离开这里。', + cht='找藉口離開這裡。', + en='Find a excuse and leave this place.', + jp='言い訳を見つけてここを離れる', + es='Encuentra una excusa y deja este lugar.', +) +Pale_gold = RogueEventOption( + id=412, + name='Pale_gold', + cn='淡金色。', + cht='淡金色。', + en='Pale gold.', + jp='淡い金色', + es='Oro pálido.', +) +Blood_red = RogueEventOption( + id=413, + name='Blood_red', + cn='血红色。', + cht='血紅色。', + en='Blood red.', + jp='血のような赤色', + es='Rojo sangre.', +) +Dark_gray = RogueEventOption( + id=414, + name='Dark_gray', + cn='深灰色。', + cht='深灰色。', + en='Dark gray.', + jp='濃い灰色', + es='Gris oscuro.', +) +Remove_the_creation = RogueEventOption( + id=415, + name='Remove_the_creation', + cn='取出造物。', + cht='取出造物。', + en='Remove the creation.', + jp='造物を取り出す', + es='Retira la creación.', +) +Security_Verification_Failed_Leave_for_now = RogueEventOption( + id=416, + name='Security_Verification_Failed_Leave_for_now', + cn='密保验证失败,先离开吧。', + cht='驗證失敗,先離開吧。', + en='Security Verification Failed. Leave for now.', + jp='セキュリティ認証失敗、一旦離れよう', + es='Verificación de seguridad fallida. Vete por ahora.', +) +Device_IX_unit_compound = RogueEventOption( + id=417, + name='Device_IX_unit_compound', + cn='第Ⅸ机关单位大院。', + cht='第Ⅸ機關單位大院。', + en='Device IX unit compound.', + jp='第IX機関の敷地内', + es='Recinto de la unidad Dispositivo IX.', +) +Herta_Space_Station = RogueEventOption( + id=418, + name='Herta_Space_Station', + cn='黑塔空间站。', + cht='黑塔太空站。', + en='Herta Space Station.', + jp='宇宙ステーション「ヘルタ」', + es='Estación Espacial Herta.', +) +Superalloy_concrete = RogueEventOption( + id=419, + name='Superalloy_concrete', + cn='超合金混凝土。', + cht='超合金混凝土。', + en='Superalloy concrete.', + jp='超合金コンクリート', + es='Cemento superaleado.', +) +Homo_sapiens = RogueEventOption( + id=420, + name='Homo_sapiens', + cn='智人。', + cht='智人。', + en='Homo sapiens.', + jp='ホモ・サピエンス', + es='Homo sapiens.', +) +Insect_eating_fungi = RogueEventOption( + id=421, + name='Insect_eating_fungi', + cn='食虫菌毯。', + cht='食蟲菌毯。', + en='Insect-eating fungi.', + jp='食虫微生物マット', + es='Hongos que se alimentan de insectos.', +) +Retrieve_the_bank_card = RogueEventOption( + id=422, + name='Retrieve_the_bank_card', + cn='取走银行卡。', + cht='拿走銀行卡。', + en='Retrieve the bank card.', + jp='キャッシュカードを取る', + es='Recupera la tarjeta de banco.', +) +Withdraw_investment = RogueEventOption( + id=423, + name='Withdraw_investment', + cn='提取本金。', + cht='提取本金。', + en='Withdraw investment.', + jp='元金を引き出す', + es='Retira el efectivo.', +) +Withdraw_interest = RogueEventOption( + id=424, + name='Withdraw_interest', + cn='提取利息。', + cht='提取利息。', + en='Withdraw interest.', + jp='利息を引き出す', + es='Retira los intereses.', +) +Withdraw_knowledge = RogueEventOption( + id=425, + name='Withdraw_knowledge', + cn='提取知识。', + cht='提取知識。', + en='Withdraw knowledge.', + jp='知識を引き出す', + es='Retira el conocimiento.', +) +Withdraw_memories = RogueEventOption( + id=426, + name='Withdraw_memories', + cn='提取记忆。', + cht='提取記憶。', + en='Withdraw memories.', + jp='記憶を引き出す', + es='Retira los recuerdos.', +) +The_extremity_of_a_tomato = RogueEventOption( + id=427, + name='The_extremity_of_a_tomato', + cn='西红柿的末端。', + cht='蕃茄的末端。', + en='The extremity of a tomato.', + jp='トマトのヘタの部分', + es='La extremidad de un tomate.', +) +Press_it = RogueEventOption( + id=428, + name='Press_it', + cn='按下它。', + cht='按下它。', + en='Press it.', + jp='それを押す', + es='Presiona.', +) +Remove_your_hand = RogueEventOption( + id=429, + name='Remove_your_hand', + cn='把手拿开。', + cht='把手拿開。', + en='Remove your hand.', + jp='手を離す', + es='Quita la mano.', +) +You_re_teaching_me_how_to_do_my_job = RogueEventOption( + id=430, + name='You_re_teaching_me_how_to_do_my_job', + cn='你在教我做事?', + cht='你在教我做事?', + en="You're teaching me how to do my job?", + jp='に指図するの?', + es='¿Me estás diciendo cómo hacer mi trabajo?', +) +Be_receptive_to_feedback = RogueEventOption( + id=431, + name='Be_receptive_to_feedback', + cn='要善于听取意见。', + cht='要善於聽取意見。', + en='Be receptive to feedback.', + jp='意見をよく聞くべきだ', + es='Mantente abiert a los comentarios.', +) +I_told_you_to_stop_pressing_the_button = RogueEventOption( + id=432, + name='I_told_you_to_stop_pressing_the_button', + cn='都叫你别按按钮了。', + cht='都叫你別按按鈕了。', + en='I told you to stop pressing the button.', + jp='もうボタンを押すなと言っているのに', + es='Te dije que no presionaras el botón.', +) +Xianzhou_collab_set_meal = RogueEventOption( + id=433, + name='Xianzhou_collab_set_meal', + cn='仙舟联名套餐。', + cht='仙舟聯名套餐。', + en='Xianzhou collab set meal.', + jp='仙舟同盟コラボセット', + es='Menú de colaboración de Xianzhou.', +) +Terrorbird_fruit_stew = RogueEventOption( + id=434, + name='Terrorbird_fruit_stew', + cn='骇鸟水果乱炖。', + cht='駭鳥水果亂燉。', + en='Terrorbird-fruit stew.', + jp='フォルスラコスフルーツのごった煮', + es='Estofado de fruta terrorpájaro.', +) +The_big_data_will_provide_the_answers = RogueEventOption( + id=435, + name='The_big_data_will_provide_the_answers', + cn='大数据会给出答案。', + cht='大資料會給出答案。', + en='The big data will provide the answers.', + jp='ビッグデータが答えを出してくれる', + es='Los macrodatos darán las respuestas.', +) +Awesome_big_W = RogueEventOption( + id=436, + name='Awesome_big_W', + cn='真好,赚到。', + cht='真好,賺到。', + en='Awesome, big W.', + jp='よかった、得した', + es='Genial, una buena ganancia.', +) +Life_support_meal_combo = RogueEventOption( + id=437, + name='Life_support_meal_combo', + cn='生命维持套餐。', + cht='生命維持套餐。', + en='Life support meal combo.', + jp='生命維持セット', + es='Comida de soporte vital.', +) +Challenge_A_sentence_of_ten_words = RogueEventOption( + id=438, + name='Challenge_A_sentence_of_ten_words', + cn='挑战十个字的句子。', + cht='挑戰十個字的句子。', + en='Challenge: A sentence of ten words.', + jp='10文字の文章に挑戦する', + es='Desafío: una frase de diez palabras.', +) +Challenge_Two_short_sentences_of_five_words_each = RogueEventOption( + id=439, + name='Challenge_Two_short_sentences_of_five_words_each', + cn='挑战两个五字短语。', + cht='挑戰兩個五字短語。', + en='Challenge: Two short sentences of five words each.', + jp='5文字の短文2つに挑戦する', + es='Desafío: dos frases cortas de cinco palabras cada una.', +) +Disassemble_the_characters_it_carries = RogueEventOption( + id=440, + name='Disassemble_the_characters_it_carries', + cn='拆散它携带的字符。', + cht='拆散它攜帶的字元。', + en='Disassemble the characters it carries.', + jp='持っている文字をバラバラにする', + es='Desmonta las letras que lleva.', +) +Choose_Pineapple = RogueEventOption( + id=441, + name='Choose_Pineapple', + cn='选择菠萝。', + cht='選擇鳳梨。', + en='Choose Pineapple.', + jp='パイナップルを選ぶ', + es='Elige la piña.', +) +Choose_Bread = RogueEventOption( + id=442, + name='Choose_Bread', + cn='选择面包。', + cht='選擇麵包。', + en='Choose Bread.', + jp='パンを選ぶ', + es='Elige el pan.', +) +Take_a_drink_and_calm_down = RogueEventOption( + id=443, + name='Take_a_drink_and_calm_down', + cn='喝瓶水冷静冷静。', + cht='喝瓶水冷靜一下。', + en='Take a drink and calm down.', + jp='水を飲んで落ち着こう', + es='Tómate una bebida y cálmate.', +) +I_will_not_turn_my_back_on_humanity = RogueEventOption( + id=444, + name='I_will_not_turn_my_back_on_humanity', + cn='我绝不会背叛人类。', + cht='我絕不會背叛人類。', + en='I will not turn my back on humanity.', + jp='絶対に人を裏切ったりしない', + es='Nunca traicionaré a la humanidad.', +) +I_am_the_king_of_trashcans = RogueEventOption( + id=445, + name='I_am_the_king_of_trashcans', + cn='我才是垃圾桶之王!', + cht='我才是垃圾桶之王!', + en='I am the king of trashcans!', + jp='ゴミ箱の王はこのだ!', + es='¡Soy el rey de los cubos de basura!', +) +Reforge_weapon = RogueEventOption( + id=446, + name='Reforge_weapon', + cn='重铸武器。', + cht='重鑄武器。', + en='Reforge weapon.', + jp='武器を鋳造し直す', + es='Vuelve a forjar un arma.', +) +Smelt_weapon = RogueEventOption( + id=447, + name='Smelt_weapon', + cn='熔炼武器。', + cht='熔鍊武器。', + en='Smelt weapon.', + jp='武器を溶解し、製錬する', + es='Funde un arma.', +) +Precision_forge_weapon = RogueEventOption( + id=448, + name='Precision_forge_weapon', + cn='精锻武器。', + cht='精鍛武器。', + en='Precision-forge weapon.', + jp='武器を精密鍛造する', + es='Refina un arma de calidad.', +) +There_something_hidden_in_its_fur = RogueEventOption( + id=449, + name='There_something_hidden_in_its_fur', + cn='有什么藏在毛茸茸里。', + cht='有什麼藏在茸毛裡?', + en="There's something hidden in its fur.", + jp='ふわふわに何かが隠れている', + es='Hay algo oculto en su pelaje.', +) +Reel_in_the_line = RogueEventOption( + id=450, + name='Reel_in_the_line', + cn='收线。', + cht='收線。', + en='Reel in the line.', + jp='引き上げる', + es='Recoge el sedal.', +) +Offer_blood = RogueEventOption( + id=451, + name='Offer_blood', + cn='献上鲜血。', + cht='獻上鮮血。', + en='Offer blood.', + jp='血を捧げる', + es='Ofrece sangre.', +) +Offer_money = RogueEventOption( + id=452, + name='Offer_money', + cn='献上金钱。', + cht='獻上金錢。', + en='Offer money.', + jp='信用ポイントを捧げる', + es='Ofrece dinero.', +) +Offer_the_past = RogueEventOption( + id=453, + name='Offer_the_past', + cn='献上过去。', + cht='獻上過去。', + en='Offer the past.', + jp='過去を捧げる', + es='Ofrece el pasado.', +) +Offer_the_future = RogueEventOption( + id=454, + name='Offer_the_future', + cn='献上未来。', + cht='獻上未來。', + en='Offer the future.', + jp='未来を捧げる', + es='Ofrece el futuro.', +) +I_want_to_get_rich = RogueEventOption( + id=455, + name='I_want_to_get_rich', + cn='我想获得财富。', + cht='我想獲得財富。', + en='I want to get rich.', + jp='富を手に入れたい', + es='Quiero ser millonari.', +) +I_want_to_receive_benedictions = RogueEventOption( + id=456, + name='I_want_to_receive_benedictions', + cn='我想获得恩赐。', + cht='我想獲得恩賜。', + en='I want to receive benedictions.', + jp='恩恵を受けたい', + es='Quiero recibir bendiciones.', +) +I_want_to_touch_upon_the_unknown = RogueEventOption( + id=457, + name='I_want_to_touch_upon_the_unknown', + cn='我想触及未知。', + cht='我想觸及未知。', + en='I want to touch upon the unknown.', + jp='未知に触れたい', + es='Quiero tocar lo desconocido.', +) +I_want_to_obtain_wisdom = RogueEventOption( + id=458, + name='I_want_to_obtain_wisdom', + cn='我想触及智慧。', + cht='我想觸及智慧。', + en='I want to obtain wisdom.', + jp='知恵に触れたい', + es='Quiero sabiduría.', +) +Give_up_on_fishing = RogueEventOption( + id=459, + name='Give_up_on_fishing', + cn='放弃垂钓。', + cht='放棄垂釣。', + en='Give up on fishing.', + jp='釣りを諦める', + es='Deja de pescar.', +) +A_primordial_bloodthirsty_beast = RogueEventOption( + id=460, + name='A_primordial_bloodthirsty_beast', + cn='远古的渴血巨兽。', + cht='遠古的渴血巨獸。', + en='A primordial, bloodthirsty beast.', + jp='血に飢えた古代の巨獣', + es='Una antigua bestia sedienta de sangre.', +) +A_cooking_Lordly_Trashcan = RogueEventOption( + id=461, + name='A_cooking_Lordly_Trashcan', + cn='下厨的王下一桶。', + cht='下廚的王下一桶。', + en='A cooking Lordly Trashcan.', + jp='料理をする王のゴミ箱', + es='Un Cubo de basura señorial cocinillas.', +) +A_game_of_Rock_Paper_Scissors_with_the_calculator = RogueEventOption( + id=462, + name='A_game_of_Rock_Paper_Scissors_with_the_calculator', + cn='计算机的猜拳游戏。', + cht='電腦的猜拳遊戲。', + en='A game of Rock, Paper, Scissors with the calculator.', + jp='コンピュータのじゃんけんゲーム', + es='Una ronda de piedra, papel o tijera de la calculadora.', +) +Last_night_dream = RogueEventOption( + id=463, + name='Last_night_dream', + cn='昨晚的梦。', + cht='昨晚的夢。', + en="Last night's dream.", + jp='昨日の夢', + es='El sueño de anoche.', +) +Pom_Pom_tail = RogueEventOption( + id=464, + name='Pom_Pom_tail', + cn='帕姆的尾巴。', + cht='帕姆的尾巴。', + en="Pom-Pom's tail.", + jp='パムの尻尾', + es='La cola de Pom-Pom.', +) +Himeko_coffee = RogueEventOption( + id=465, + name='Himeko_coffee', + cn='姬子的咖啡。', + cht='姬子的咖啡。', + en="Himeko's coffee.", + jp='姫子のコーヒー', + es='El café de Himeko.', +) +Bounty_Hunter_of_the_Snow_Plains = RogueEventOption( + id=466, + name='Bounty_Hunter_of_the_Snow_Plains', + cn='雪原的赏金猎人。', + cht='雪原的賞金獵人。', + en='Bounty Hunter of the Snow Plains.', + jp='雪原の賞金稼ぎ', + es='Cazarrecompensas de las llanuras nevadas.', +) +An_Aha_Stuffed_Toy_asking_to_be_hit = RogueEventOption( + id=467, + name='An_Aha_Stuffed_Toy_asking_to_be_hit', + cn='欠揍的阿哈玩偶。', + cht='欠揍的阿哈玩偶。', + en='An Aha Stuffed Toy asking to be hit.', + jp='ムカつくアッハ人形', + es='Un muñeco de Aha que quiere que lo golpeen.', +) +The_library_History_Fictionologist = RogueEventOption( + id=468, + name='The_library_History_Fictionologist', + cn='图书馆的虚构史学家。', + cht='圖書館的虛構史學家。', + en="The library's History Fictionologist.", + jp='図書館にいる虚構歴史学者', + es='Los Historiadores Espurios de la biblioteca.', +) +Describe_a_colorful_journey = RogueEventOption( + id=469, + name='Describe_a_colorful_journey', + cn='讲述多彩的旅途。', + cht='講述多彩的旅途。', + en='Describe a colorful journey.', + jp='多彩な旅の話をする', + es='Describe un viaje extravagante.', +) +Describe_a_wondrous_adventure = RogueEventOption( + id=470, + name='Describe_a_wondrous_adventure', + cn='讲述惊奇的冒险。', + cht='講述驚奇的冒險。', + en='Describe a wondrous adventure.', + jp='不思議な冒険の話をする', + es='Describe una aventura maravillosa.', +) +Describe_a_simple_life = RogueEventOption( + id=471, + name='Describe_a_simple_life', + cn='讲述朴实的生活。', + cht='講述樸實的生活。', + en='Describe a simple life.', + jp='素朴な生活の話をする', + es='Describe una vida simple.', +) +Recount_your_empty_past = RogueEventOption( + id=472, + name='Recount_your_empty_past', + cn='讲述空白的过往。', + cht='講述空白的過往。', + en='Recount your empty past.', + jp='空っぽな過去を語る', + es='Describe tu vacío pasado.', +) +Chasing_excitement = RogueEventOption( + id=473, + name='Chasing_excitement', + cn='玩的就是一个刺激。', + cht='越刺激就會越好玩。', + en='Chasing excitement.', + jp='エキサイティングであればあるほどいい', + es='Divertirse es emocionante.', +) +Consider_it_as_helping_out_the_Guild_business = RogueEventOption( + id=474, + name='Consider_it_as_helping_out_the_Guild_business', + cn='就当照顾学会的生意。', + cht='就當關照學會的生意。', + en="Consider it as helping out the Guild's business.", + jp='学会のビジネスを贔屓するってことで', + es='Considéralo como un apoyo a los negocios de la Sociedad.', +) diff --git a/tasks/rogue/keywords/event_title.py b/tasks/rogue/keywords/event_title.py index 6d9ea82a6..aa2236030 100644 --- a/tasks/rogue/keywords/event_title.py +++ b/tasks/rogue/keywords/event_title.py @@ -1383,3 +1383,173 @@ Ruan_Mei_III = RogueEventTitle( es='Ruan Mei III', option_ids=[392, 393, 394], ) +Special_Discount = RogueEventTitle( + id=139, + name='Special_Discount', + cn='特别优惠', + cht='特別優惠', + en='Special Discount', + jp='特別割引', + es='Descuento especial', + option_ids=[395, 396, 397, 398, 399, 400, 401, 402, 403, 404], +) +Metal_Life = RogueEventTitle( + id=140, + name='Metal_Life', + cn='金属生活', + cht='金屬生活', + en='Metal Life', + jp='金属生活', + es='Vida metálica', + option_ids=[405, 406, 407, 408, 409, 410, 411], +) +A_Dash_of_Color = RogueEventTitle( + id=141, + name='A_Dash_of_Color', + cn='一抹色彩', + cht='一抹色彩', + en='A Dash of Color', + jp='一抹の色彩', + es='Una pizca de color', + option_ids=[412, 413, 414], +) +Creation_Unit = RogueEventTitle( + id=142, + name='Creation_Unit', + cn='造物单元', + cht='造物單元', + en='Creation Unit', + jp='造物ユニット', + es='Unidad de creación', + option_ids=[415], +) +Time_Bank_I = RogueEventTitle( + id=143, + name='Time_Bank_I', + cn='时间银行(其一)', + cht='時間銀行(其一)', + en='Time Bank (I)', + jp='タイムバンク(その1)', + es='Banco del tiempo (I)', + option_ids=[416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427], +) +Time_Bank_II = RogueEventTitle( + id=144, + name='Time_Bank_II', + cn='时间银行(其二)', + cht='時間銀行(其二)', + en='Time Bank (II)', + jp='タイムバンク(その2)', + es='Banco del tiempo (II)', + option_ids=[426, 427], +) +Red_Temptation = RogueEventTitle( + id=145, + name='Red_Temptation', + cn='红色诱惑', + cht='紅色誘惑', + en='Red Temptation', + jp='赤い誘惑', + es='Tentación roja', + option_ids=[428, 429, 430, 431, 432], +) +Selection_Difficulties_I = RogueEventTitle( + id=146, + name='Selection_Difficulties_I', + cn='选择困难(其一)', + cht='選擇困難(其一)', + en='Selection Difficulties (I)', + jp='選択困難(その1)', + es='Dificultad de elección (I)', + option_ids=[433, 434, 435, 436, 437], +) +Selection_Difficulties_II = RogueEventTitle( + id=147, + name='Selection_Difficulties_II', + cn='选择困难(其二)', + cht='選擇困難(其二)', + en='Selection Difficulties (II)', + jp='選択困難(その2)', + es='Dificultad de elección (II)', + option_ids=[434, 435, 436, 437], +) +Semantic_Mismatch = RogueEventTitle( + id=148, + name='Semantic_Mismatch', + cn='语义不符', + cht='語義不符', + en='Semantic Mismatch', + jp='本義の不一致', + es='Inconsistencia semántica', + option_ids=[438, 439, 440], +) +Pineapple_Bread = RogueEventTitle( + id=149, + name='Pineapple_Bread', + cn='菠萝面包', + cht='鳳梨麵包', + en='Pineapple Bread', + jp='パイナップルパン', + es='Pan de piña', + option_ids=[441, 442, 443], +) +Trash_Symphony = RogueEventTitle( + id=150, + name='Trash_Symphony', + cn='垃圾交响曲', + cht='垃圾交響曲', + en='Trash Symphony', + jp='トラッシュシンフォニー', + es='Sinfonía de la basura', + option_ids=[444, 445], +) +Lava = RogueEventTitle( + id=151, + name='Lava', + cn='熔岩', + cht='熔岩', + en='Lava', + jp='溶岩', + es='Lava', + option_ids=[446, 447, 448], +) +Apes_Such_As_You = RogueEventTitle( + id=152, + name='Apes_Such_As_You', + cn='像你这样的苍猿', + cht='像你這樣的蒼猿', + en='Apes Such As You', + jp='あなたのような蒼猿は', + es='Simios como tú', + option_ids=[449], +) +Fishing_Ceremony = RogueEventTitle( + id=153, + name='Fishing_Ceremony', + cn='垂钓仪式', + cht='垂釣儀式', + en='Fishing Ceremony', + jp='釣りの儀式', + es='Ceremonia de pesca', + option_ids=[450, 451, 452, 453, 454, 455, 456, 457, 458, 459], +) +Flea_Market = RogueEventTitle( + id=154, + name='Flea_Market', + cn='跳蚤市场', + cht='跳蚤市場', + en='Flea Market', + jp='蚤の市', + es='Mercadillo', + option_ids=[460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472], +) +Collab_Product = RogueEventTitle( + id=155, + name='Collab_Product', + cn='联名产品', + cht='聯名產品', + en='Collab Product', + jp='コラボ商品', + es='Producto de colaboración', + option_ids=[5, 473, 474], +)