Add: character and combat support (#38)
* Add: combat support * Fix: team_set logic when using support in combat * Add: Support character selection * Upd: optimize support character get logic * Fix: bug in get_character_by_name * Upd: use keywords to generate support config * Fix: Correct comment language to English * Fix: Remove debug statements * Upd: Improve UI icons and positioning * Upd: Refactor support * Upd: character keyword extract * Upd:Character icon * Upd: Character icon * Upd: Character icon * Upd: Optimize the parameter in SupportListScroll * Upd: Refactor support * Fix: Bug in Dungeon * Fix: Corrected comments in Combat and Support * Upd: Modified parameter * Refactor: Support logic * Refactor: Support logic * Refactor: Support logic * Upd: Character icon * Upd: Character icon * Refactor: Support logic * Refactor: Support logic
BIN
assets/character/Arlan.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/character/Asta.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/character/Bailu.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/Bronya.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/CaelumtheDestruction.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/CaelumthePreservation.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
assets/character/Clara.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/DanHeng.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
assets/character/Gepard.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/Herta.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/character/Himeko.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/Hook.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/JingYuan.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
assets/character/Luocha.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/March7th.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/Natasha.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/character/Pela.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/Qingque.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/Sampo.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/character/Seele.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/Serval.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/SilverWolf.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
assets/character/StelletheDestruction.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/StellethePreservation.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/Sushang.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/character/Tingyun.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/Welt.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/character/Yanqing.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/character/Yukong.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/share/combat/support/COMBAT_SUPPORT_ADD.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
assets/share/combat/support/COMBAT_SUPPORT_LIST.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png
Normal file
After Width: | Height: | Size: 114 KiB |
BIN
assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
assets/share/combat/support/COMBAT_SUPPORT_SELECTED.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
assets/share/combat/team/COMBAT_TEAM_DISMISSSUPPORT.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
assets/share/combat/team/COMBAT_TEAM_SUPPORT.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
@ -42,7 +42,9 @@
|
||||
"Dungeon": {
|
||||
"Name": "Calyx_Golden_Treasures",
|
||||
"NameAtDoubleCalyx": "Calyx_Golden_Treasures",
|
||||
"Team": 1
|
||||
"Team": 1,
|
||||
"Support": "when_daily",
|
||||
"SupportCharacter": "FirstCharacter"
|
||||
}
|
||||
},
|
||||
"DailyQuest": {
|
||||
|
@ -25,7 +25,16 @@ def dungeon_name(name: str) -> str:
|
||||
name = re.sub('Bud_of_(.*)', r'Calyx_Crimson_\1', name).replace('Calyx_Crimson_Calyx_Crimson_', 'Calyx_Crimson_')
|
||||
name = re.sub('Shape_of_(.*)', r'Stagnant_Shadow_\1', name)
|
||||
if name in ['Destructions_Beginning', 'End_of_the_Eternal_Freeze']:
|
||||
name = 'Echo_of_War_' + name
|
||||
name = f'Echo_of_War_{name}'
|
||||
return name
|
||||
|
||||
|
||||
nickname_count = 0
|
||||
|
||||
|
||||
def character_name(name: str) -> str:
|
||||
name = text_to_variable(name)
|
||||
name = re.sub('_', '', name)
|
||||
return name
|
||||
|
||||
|
||||
@ -44,6 +53,7 @@ class TextMap:
|
||||
data = {}
|
||||
for id_, text in read_file(file).items():
|
||||
text = text.replace('\u00A0', '')
|
||||
text = text.replace(r'{NICKNAME}', 'Trailblazer')
|
||||
data[int(id_)] = text
|
||||
return data
|
||||
|
||||
@ -177,6 +187,18 @@ class KeywordExtract:
|
||||
quest_keywords = [self.text_map[lang].find(quest_hash)[1] for quest_hash in quests_hash]
|
||||
self.load_keywords(quest_keywords, lang)
|
||||
|
||||
def load_character_name_keywords(self, lang='en'):
|
||||
file_name = 'ItemConfigAvatarPlayerIcon.json'
|
||||
path = os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', file_name)
|
||||
character_data = read_file(path)
|
||||
characters_hash = [character_data[key]["ItemName"]["Hash"] for key in character_data]
|
||||
|
||||
text_map = self.text_map[lang]
|
||||
keywords_id = sorted(
|
||||
{text_map.find(keyword)[1] for keyword in characters_hash}
|
||||
)
|
||||
self.load_keywords(keywords_id, lang)
|
||||
|
||||
def generate_forgotten_hall_stages(self):
|
||||
keyword_class = "ForgottenHallStage"
|
||||
output_file = './tasks/forgotten_hall/keywords/stage.py'
|
||||
@ -230,6 +252,11 @@ class KeywordExtract:
|
||||
text_convert=text_convert(world), generator=gen)
|
||||
gen.write('./tasks/map/keywords/plane.py')
|
||||
|
||||
def generate_character_keywords(self):
|
||||
self.load_character_name_keywords()
|
||||
self.write_keywords(keyword_class='CharacterList', output_file='./tasks/character/keywords/character_list.py',
|
||||
text_convert=character_name)
|
||||
|
||||
def generate(self):
|
||||
self.load_keywords(['模拟宇宙', '拟造花萼(金)', '拟造花萼(赤)', '凝滞虚影', '侵蚀隧洞', '历战余响', '忘却之庭'])
|
||||
self.write_keywords(keyword_class='DungeonNav', output_file='./tasks/dungeon/keywords/nav.py')
|
||||
@ -249,6 +276,7 @@ class KeywordExtract:
|
||||
self.generate_assignment_keywords()
|
||||
self.generate_forgotten_hall_stages()
|
||||
self.generate_map_planes()
|
||||
self.generate_character_keywords()
|
||||
self.load_keywords(['养成材料', '光锥', '遗器', '其他材料', '消耗品', '任务', '贵重物'])
|
||||
self.write_keywords(keyword_class='ItemTab', text_convert=lambda name: name.replace(' ', ''),
|
||||
output_file='./tasks/item/keywords/tab.py')
|
||||
|
@ -227,6 +227,50 @@
|
||||
5,
|
||||
6
|
||||
]
|
||||
},
|
||||
"Support": {
|
||||
"type": "select",
|
||||
"value": "when_daily",
|
||||
"option": [
|
||||
"do_not_use",
|
||||
"always_use",
|
||||
"when_daily"
|
||||
]
|
||||
},
|
||||
"SupportCharacter": {
|
||||
"type": "select",
|
||||
"value": "FirstCharacter",
|
||||
"option": [
|
||||
"FirstCharacter",
|
||||
"Arlan",
|
||||
"Asta",
|
||||
"Bailu",
|
||||
"Bronya",
|
||||
"Clara",
|
||||
"DanHeng",
|
||||
"Gepard",
|
||||
"Herta",
|
||||
"Himeko",
|
||||
"Hook",
|
||||
"JingYuan",
|
||||
"Kafka",
|
||||
"Luocha",
|
||||
"March7th",
|
||||
"Natasha",
|
||||
"Pela",
|
||||
"Qingque",
|
||||
"Sampo",
|
||||
"Seele",
|
||||
"Serval",
|
||||
"SilverWolf",
|
||||
"Sushang",
|
||||
"Tingyun",
|
||||
"TrailblazertheDestruction",
|
||||
"TrailblazerthePreservation",
|
||||
"Welt",
|
||||
"Yanqing",
|
||||
"Yukong"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -81,6 +81,13 @@ Dungeon:
|
||||
Team:
|
||||
value: 1
|
||||
option: [ 1, 2, 3, 4, 5, 6 ]
|
||||
Support:
|
||||
value: when_daily
|
||||
option: [do_not_use, always_use, when_daily]
|
||||
SupportCharacter:
|
||||
# Options will be injected in config updater
|
||||
value: FirstCharacter
|
||||
option: [FirstCharacter, ]
|
||||
|
||||
Assignment:
|
||||
Duration:
|
||||
|
@ -42,6 +42,8 @@ class GeneratedConfig:
|
||||
Dungeon_Name = 'Calyx_Golden_Treasures' # Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility, Stagnant_Shadow_Quanta, Stagnant_Shadow_Gust, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Blaze, Stagnant_Shadow_Spike, Stagnant_Shadow_Rime, Stagnant_Shadow_Mirage, Stagnant_Shadow_Icicle, Stagnant_Shadow_Doom, 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
|
||||
Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures' # do_not_participate, Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility
|
||||
Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6
|
||||
Dungeon_Support = 'when_daily' # do_not_use, always_use, when_daily
|
||||
Dungeon_SupportCharacter = 'FirstCharacter' # FirstCharacter, Arlan, Asta, Bailu, Bronya, Clara, DanHeng, Gepard, Herta, Himeko, Hook, JingYuan, Kafka, Luocha, March7th, Natasha, Pela, Qingque, Sampo, Seele, Serval, SilverWolf, Sushang, Tingyun, TrailblazertheDestruction, TrailblazerthePreservation, Welt, Yanqing, Yukong
|
||||
|
||||
# Group `Assignment`
|
||||
Assignment_Duration = 20 # 4, 8, 12, 20
|
||||
|
@ -1,11 +1,10 @@
|
||||
import re
|
||||
from copy import deepcopy
|
||||
|
||||
from cached_property import cached_property
|
||||
|
||||
from deploy.Windows.utils import DEPLOY_TEMPLATE, poor_yaml_read, poor_yaml_write
|
||||
from module.base.timer import timer
|
||||
from module.config.server import to_server, to_package, VALID_PACKAGE, VALID_CHANNEL_PACKAGE
|
||||
from module.config.server import to_package, VALID_PACKAGE, VALID_CHANNEL_PACKAGE
|
||||
from module.config.utils import *
|
||||
|
||||
CONFIG_IMPORT = '''
|
||||
@ -290,6 +289,16 @@ class ConfigGenerator:
|
||||
if value:
|
||||
deep_set(new, keys=['Dungeon', 'NameAtDoubleCalyx', dungeon], value=value)
|
||||
|
||||
from tasks.character.keywords import CharacterList
|
||||
ingame_lang = gui_lang_to_ingame_lang(lang)
|
||||
characters = deep_get(self.argument, keys='Dungeon.SupportCharacter.option')
|
||||
for character in CharacterList.instances.values():
|
||||
if character.name in characters:
|
||||
value = character.__getattribute__(ingame_lang)
|
||||
if "Trailblazer" in value:
|
||||
continue
|
||||
deep_set(new, keys=['Dungeon', 'SupportCharacter', character.name], value=value)
|
||||
|
||||
# GUI i18n
|
||||
for path, _ in deep_iter(self.gui, depth=2):
|
||||
group, key = path
|
||||
@ -362,6 +371,12 @@ class ConfigGenerator:
|
||||
dungeons = [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_daily_dungeon]
|
||||
deep_set(self.argument, keys='Dungeon.Name.option', value=dungeons)
|
||||
deep_set(self.args, keys='Dungeon.Dungeon.Name.option', value=dungeons)
|
||||
|
||||
from tasks.character.keywords import CharacterList
|
||||
characters = ['FirstCharacter'] + [character.name for character in CharacterList.instances.values()]
|
||||
deep_set(self.argument, keys='Dungeon.SupportCharacter.option', value=characters)
|
||||
deep_set(self.args, keys='Dungeon.Dungeon.SupportCharacter.option', value=characters)
|
||||
|
||||
dungeons = deep_get(self.argument, keys='Dungeon.NameAtDoubleCalyx.option')
|
||||
dungeons += [dungeon.name for dungeon in DungeonList.instances.values()
|
||||
if dungeon.is_Calyx_Golden or dungeon.is_Calyx_Crimson]
|
||||
|
@ -233,6 +233,46 @@
|
||||
"4": "4",
|
||||
"5": "5",
|
||||
"6": "6"
|
||||
},
|
||||
"Support": {
|
||||
"name": "Enable buddy support",
|
||||
"help": "Whether to enable buddy support",
|
||||
"do_not_use": "do_not_use",
|
||||
"always_use": "always_use",
|
||||
"when_daily": "when_daily"
|
||||
},
|
||||
"SupportCharacter": {
|
||||
"name": "Dungeon.SupportCharacter.name",
|
||||
"help": "Dungeon.SupportCharacter.help",
|
||||
"FirstCharacter": "FirstCharacter",
|
||||
"Arlan": "Arlan",
|
||||
"Asta": "Asta",
|
||||
"Bailu": "Bailu",
|
||||
"Bronya": "Bronya",
|
||||
"Clara": "Clara",
|
||||
"DanHeng": "Dan Heng",
|
||||
"Gepard": "Gepard",
|
||||
"Herta": "Herta",
|
||||
"Himeko": "Himeko",
|
||||
"Hook": "Hook",
|
||||
"JingYuan": "Jing Yuan",
|
||||
"Kafka": "Kafka",
|
||||
"Luocha": "Luocha",
|
||||
"March7th": "March 7th",
|
||||
"Natasha": "Natasha",
|
||||
"Pela": "Pela",
|
||||
"Qingque": "Qingque",
|
||||
"Sampo": "Sampo",
|
||||
"Seele": "Seele",
|
||||
"Serval": "Serval",
|
||||
"SilverWolf": "Silver Wolf",
|
||||
"Sushang": "Sushang",
|
||||
"Tingyun": "Tingyun",
|
||||
"TrailblazertheDestruction": "Trailblazer: the Destruction",
|
||||
"TrailblazerthePreservation": "Trailblazer: the Preservation",
|
||||
"Welt": "Welt",
|
||||
"Yanqing": "Yanqing",
|
||||
"Yukong": "Yukong"
|
||||
}
|
||||
},
|
||||
"Assignment": {
|
||||
|
@ -233,6 +233,46 @@
|
||||
"4": "4",
|
||||
"5": "5",
|
||||
"6": "6"
|
||||
},
|
||||
"Support": {
|
||||
"name": "Dungeon.Support.name",
|
||||
"help": "Dungeon.Support.help",
|
||||
"do_not_use": "do_not_use",
|
||||
"always_use": "always_use",
|
||||
"when_daily": "when_daily"
|
||||
},
|
||||
"SupportCharacter": {
|
||||
"name": "Dungeon.SupportCharacter.name",
|
||||
"help": "Dungeon.SupportCharacter.help",
|
||||
"FirstCharacter": "FirstCharacter",
|
||||
"Arlan": "アーラン",
|
||||
"Asta": "アスター",
|
||||
"Bailu": "白露",
|
||||
"Bronya": "ブローニャ",
|
||||
"Clara": "クラーラ",
|
||||
"DanHeng": "丹恒",
|
||||
"Gepard": "ジェパード",
|
||||
"Herta": "ヘルタ",
|
||||
"Himeko": "姫子",
|
||||
"Hook": "フック",
|
||||
"JingYuan": "景元",
|
||||
"Kafka": "カフカ",
|
||||
"Luocha": "羅刹",
|
||||
"March7th": "三月なのか",
|
||||
"Natasha": "ナターシャ",
|
||||
"Pela": "ペラ",
|
||||
"Qingque": "青雀",
|
||||
"Sampo": "サンポ",
|
||||
"Seele": "ゼーレ",
|
||||
"Serval": "セーバル",
|
||||
"SilverWolf": "銀狼",
|
||||
"Sushang": "素裳",
|
||||
"Tingyun": "停雲",
|
||||
"TrailblazertheDestruction": "Trailblazer・壊滅",
|
||||
"TrailblazerthePreservation": "Trailblazer・存護",
|
||||
"Welt": "ヴェルト",
|
||||
"Yanqing": "彦卿",
|
||||
"Yukong": "御空"
|
||||
}
|
||||
},
|
||||
"Assignment": {
|
||||
|
@ -233,6 +233,46 @@
|
||||
"4": "4",
|
||||
"5": "5",
|
||||
"6": "6"
|
||||
},
|
||||
"Support": {
|
||||
"name": "启用好友支援",
|
||||
"help": "是否启用好友支援",
|
||||
"do_not_use": "否",
|
||||
"always_use": "是",
|
||||
"when_daily": "仅当每日任务需要时"
|
||||
},
|
||||
"SupportCharacter": {
|
||||
"name": "好友支援角色",
|
||||
"help": "选择好友支援角色,未找到则选择默认(第一个)角色",
|
||||
"FirstCharacter": "支援列表第一个角色",
|
||||
"Arlan": "阿兰",
|
||||
"Asta": "艾丝妲",
|
||||
"Bailu": "白露",
|
||||
"Bronya": "布洛妮娅",
|
||||
"Clara": "克拉拉",
|
||||
"DanHeng": "丹恒",
|
||||
"Gepard": "杰帕德",
|
||||
"Herta": "黑塔",
|
||||
"Himeko": "姬子",
|
||||
"Hook": "虎克",
|
||||
"JingYuan": "景元",
|
||||
"Kafka": "卡芙卡(未实装)",
|
||||
"Luocha": "罗刹",
|
||||
"March7th": "三月七",
|
||||
"Natasha": "娜塔莎",
|
||||
"Pela": "佩拉",
|
||||
"Qingque": "青雀",
|
||||
"Sampo": "桑博",
|
||||
"Seele": "希儿",
|
||||
"Serval": "希露瓦",
|
||||
"SilverWolf": "银狼",
|
||||
"Sushang": "素裳",
|
||||
"Tingyun": "停云",
|
||||
"TrailblazertheDestruction": "开拓者•毁灭",
|
||||
"TrailblazerthePreservation": "开拓者•存护",
|
||||
"Welt": "瓦尔特",
|
||||
"Yanqing": "彦卿",
|
||||
"Yukong": "驭空"
|
||||
}
|
||||
},
|
||||
"Assignment": {
|
||||
|
@ -233,6 +233,46 @@
|
||||
"4": "4",
|
||||
"5": "5",
|
||||
"6": "6"
|
||||
},
|
||||
"Support": {
|
||||
"name": "Dungeon.Support.name",
|
||||
"help": "Dungeon.Support.help",
|
||||
"do_not_use": "do_not_use",
|
||||
"always_use": "always_use",
|
||||
"when_daily": "when_daily"
|
||||
},
|
||||
"SupportCharacter": {
|
||||
"name": "Dungeon.SupportCharacter.name",
|
||||
"help": "Dungeon.SupportCharacter.help",
|
||||
"FirstCharacter": "FirstCharacter",
|
||||
"Arlan": "阿蘭",
|
||||
"Asta": "艾絲妲",
|
||||
"Bailu": "白露",
|
||||
"Bronya": "布洛妮婭",
|
||||
"Clara": "克拉拉",
|
||||
"DanHeng": "丹恆",
|
||||
"Gepard": "傑帕德",
|
||||
"Herta": "黑塔",
|
||||
"Himeko": "姬子",
|
||||
"Hook": "虎克",
|
||||
"JingYuan": "景元",
|
||||
"Kafka": "卡芙卡",
|
||||
"Luocha": "羅剎",
|
||||
"March7th": "三月七",
|
||||
"Natasha": "娜塔莎",
|
||||
"Pela": "佩拉",
|
||||
"Qingque": "青雀",
|
||||
"Sampo": "桑博",
|
||||
"Seele": "希兒",
|
||||
"Serval": "希露瓦",
|
||||
"SilverWolf": "銀狼",
|
||||
"Sushang": "素裳",
|
||||
"Tingyun": "停雲",
|
||||
"TrailblazertheDestruction": "Trailblazer•毀滅",
|
||||
"TrailblazerthePreservation": "Trailblazer•存護",
|
||||
"Welt": "瓦爾特",
|
||||
"Yanqing": "彥卿",
|
||||
"Yukong": "馭空"
|
||||
}
|
||||
},
|
||||
"Assignment": {
|
||||
|
2
tasks/character/keywords/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
import tasks.character.keywords.character_list as KEYWORD_CHARACTER_LIST
|
||||
from tasks.character.keywords.classes import CharacterList
|
229
tasks/character/keywords/character_list.py
Normal file
@ -0,0 +1,229 @@
|
||||
from .classes import CharacterList
|
||||
|
||||
# This file was auto-generated, do not modify it manually. To generate:
|
||||
# ``` python -m dev_tools.keyword_extract ```
|
||||
|
||||
Arlan = CharacterList(
|
||||
id=1,
|
||||
name='Arlan',
|
||||
cn='阿兰',
|
||||
cht='阿蘭',
|
||||
en='Arlan',
|
||||
jp='アーラン',
|
||||
)
|
||||
Asta = CharacterList(
|
||||
id=2,
|
||||
name='Asta',
|
||||
cn='艾丝妲',
|
||||
cht='艾絲妲',
|
||||
en='Asta',
|
||||
jp='アスター',
|
||||
)
|
||||
Bailu = CharacterList(
|
||||
id=3,
|
||||
name='Bailu',
|
||||
cn='白露',
|
||||
cht='白露',
|
||||
en='Bailu',
|
||||
jp='白露',
|
||||
)
|
||||
Bronya = CharacterList(
|
||||
id=4,
|
||||
name='Bronya',
|
||||
cn='布洛妮娅',
|
||||
cht='布洛妮婭',
|
||||
en='Bronya',
|
||||
jp='ブローニャ',
|
||||
)
|
||||
Clara = CharacterList(
|
||||
id=5,
|
||||
name='Clara',
|
||||
cn='克拉拉',
|
||||
cht='克拉拉',
|
||||
en='Clara',
|
||||
jp='クラーラ',
|
||||
)
|
||||
DanHeng = CharacterList(
|
||||
id=6,
|
||||
name='DanHeng',
|
||||
cn='丹恒',
|
||||
cht='丹恆',
|
||||
en='Dan Heng',
|
||||
jp='丹恒',
|
||||
)
|
||||
Gepard = CharacterList(
|
||||
id=7,
|
||||
name='Gepard',
|
||||
cn='杰帕德',
|
||||
cht='傑帕德',
|
||||
en='Gepard',
|
||||
jp='ジェパード',
|
||||
)
|
||||
Herta = CharacterList(
|
||||
id=8,
|
||||
name='Herta',
|
||||
cn='黑塔',
|
||||
cht='黑塔',
|
||||
en='Herta',
|
||||
jp='ヘルタ',
|
||||
)
|
||||
Himeko = CharacterList(
|
||||
id=9,
|
||||
name='Himeko',
|
||||
cn='姬子',
|
||||
cht='姬子',
|
||||
en='Himeko',
|
||||
jp='姫子',
|
||||
)
|
||||
Hook = CharacterList(
|
||||
id=10,
|
||||
name='Hook',
|
||||
cn='虎克',
|
||||
cht='虎克',
|
||||
en='Hook',
|
||||
jp='フック',
|
||||
)
|
||||
JingYuan = CharacterList(
|
||||
id=11,
|
||||
name='JingYuan',
|
||||
cn='景元',
|
||||
cht='景元',
|
||||
en='Jing Yuan',
|
||||
jp='景元',
|
||||
)
|
||||
Kafka = CharacterList(
|
||||
id=12,
|
||||
name='Kafka',
|
||||
cn='卡芙卡',
|
||||
cht='卡芙卡',
|
||||
en='Kafka',
|
||||
jp='カフカ',
|
||||
)
|
||||
Luocha = CharacterList(
|
||||
id=13,
|
||||
name='Luocha',
|
||||
cn='罗刹',
|
||||
cht='羅剎',
|
||||
en='Luocha',
|
||||
jp='羅刹',
|
||||
)
|
||||
March7th = CharacterList(
|
||||
id=14,
|
||||
name='March7th',
|
||||
cn='三月七',
|
||||
cht='三月七',
|
||||
en='March 7th',
|
||||
jp='三月なのか',
|
||||
)
|
||||
Natasha = CharacterList(
|
||||
id=15,
|
||||
name='Natasha',
|
||||
cn='娜塔莎',
|
||||
cht='娜塔莎',
|
||||
en='Natasha',
|
||||
jp='ナターシャ',
|
||||
)
|
||||
Pela = CharacterList(
|
||||
id=16,
|
||||
name='Pela',
|
||||
cn='佩拉',
|
||||
cht='佩拉',
|
||||
en='Pela',
|
||||
jp='ペラ',
|
||||
)
|
||||
Qingque = CharacterList(
|
||||
id=17,
|
||||
name='Qingque',
|
||||
cn='青雀',
|
||||
cht='青雀',
|
||||
en='Qingque',
|
||||
jp='青雀',
|
||||
)
|
||||
Sampo = CharacterList(
|
||||
id=18,
|
||||
name='Sampo',
|
||||
cn='桑博',
|
||||
cht='桑博',
|
||||
en='Sampo',
|
||||
jp='サンポ',
|
||||
)
|
||||
Seele = CharacterList(
|
||||
id=19,
|
||||
name='Seele',
|
||||
cn='希儿',
|
||||
cht='希兒',
|
||||
en='Seele',
|
||||
jp='ゼーレ',
|
||||
)
|
||||
Serval = CharacterList(
|
||||
id=20,
|
||||
name='Serval',
|
||||
cn='希露瓦',
|
||||
cht='希露瓦',
|
||||
en='Serval',
|
||||
jp='セーバル',
|
||||
)
|
||||
SilverWolf = CharacterList(
|
||||
id=21,
|
||||
name='SilverWolf',
|
||||
cn='银狼',
|
||||
cht='銀狼',
|
||||
en='Silver Wolf',
|
||||
jp='銀狼',
|
||||
)
|
||||
Sushang = CharacterList(
|
||||
id=22,
|
||||
name='Sushang',
|
||||
cn='素裳',
|
||||
cht='素裳',
|
||||
en='Sushang',
|
||||
jp='素裳',
|
||||
)
|
||||
Tingyun = CharacterList(
|
||||
id=23,
|
||||
name='Tingyun',
|
||||
cn='停云',
|
||||
cht='停雲',
|
||||
en='Tingyun',
|
||||
jp='停雲',
|
||||
)
|
||||
TrailblazertheDestruction = CharacterList(
|
||||
id=24,
|
||||
name='TrailblazertheDestruction',
|
||||
cn='Trailblazer•毁灭',
|
||||
cht='Trailblazer•毀滅',
|
||||
en='Trailblazer: the Destruction',
|
||||
jp='Trailblazer・壊滅',
|
||||
)
|
||||
TrailblazerthePreservation = CharacterList(
|
||||
id=25,
|
||||
name='TrailblazerthePreservation',
|
||||
cn='Trailblazer•存护',
|
||||
cht='Trailblazer•存護',
|
||||
en='Trailblazer: the Preservation',
|
||||
jp='Trailblazer・存護',
|
||||
)
|
||||
Welt = CharacterList(
|
||||
id=26,
|
||||
name='Welt',
|
||||
cn='瓦尔特',
|
||||
cht='瓦爾特',
|
||||
en='Welt',
|
||||
jp='ヴェルト',
|
||||
)
|
||||
Yanqing = CharacterList(
|
||||
id=27,
|
||||
name='Yanqing',
|
||||
cn='彦卿',
|
||||
cht='彥卿',
|
||||
en='Yanqing',
|
||||
jp='彦卿',
|
||||
)
|
||||
Yukong = CharacterList(
|
||||
id=28,
|
||||
name='Yukong',
|
||||
cn='驭空',
|
||||
cht='馭空',
|
||||
en='Yukong',
|
||||
jp='御空',
|
||||
)
|
8
tasks/character/keywords/classes.py
Normal file
@ -0,0 +1,8 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
|
||||
from module.ocr.keyword import Keyword
|
||||
|
||||
@dataclass(repr=False)
|
||||
class CharacterList(Keyword):
|
||||
instances: ClassVar = {}
|
55
tasks/combat/assets/assets_combat_support.py
Normal file
@ -0,0 +1,55 @@
|
||||
from module.base.button import Button, ButtonWrapper
|
||||
|
||||
# This file was auto-generated, do not modify it manually. To generate:
|
||||
# ``` python -m dev_tools.button_extract ```
|
||||
|
||||
COMBAT_SUPPORT_ADD = ButtonWrapper(
|
||||
name='COMBAT_SUPPORT_ADD',
|
||||
share=Button(
|
||||
file='./assets/share/combat/support/COMBAT_SUPPORT_ADD.png',
|
||||
area=(1032, 649, 1132, 680),
|
||||
search=(1012, 629, 1152, 700),
|
||||
color=(228, 228, 228),
|
||||
button=(1032, 649, 1132, 680),
|
||||
),
|
||||
)
|
||||
COMBAT_SUPPORT_LIST = ButtonWrapper(
|
||||
name='COMBAT_SUPPORT_LIST',
|
||||
share=Button(
|
||||
file='./assets/share/combat/support/COMBAT_SUPPORT_LIST.png',
|
||||
area=(57, 637, 100, 680),
|
||||
search=(37, 617, 120, 700),
|
||||
color=(212, 213, 215),
|
||||
button=(57, 637, 100, 680),
|
||||
),
|
||||
)
|
||||
COMBAT_SUPPORT_LIST_GRID = ButtonWrapper(
|
||||
name='COMBAT_SUPPORT_LIST_GRID',
|
||||
share=Button(
|
||||
file='./assets/share/combat/support/COMBAT_SUPPORT_LIST_GRID.png',
|
||||
area=(64, 115, 159, 634),
|
||||
search=(44, 95, 179, 654),
|
||||
color=(119, 108, 132),
|
||||
button=(64, 115, 159, 634),
|
||||
),
|
||||
)
|
||||
COMBAT_SUPPORT_LIST_SCROLL = ButtonWrapper(
|
||||
name='COMBAT_SUPPORT_LIST_SCROLL',
|
||||
share=Button(
|
||||
file='./assets/share/combat/support/COMBAT_SUPPORT_LIST_SCROLL.png',
|
||||
area=(448, 112, 452, 610),
|
||||
search=(428, 92, 472, 630),
|
||||
color=(127, 133, 150),
|
||||
button=(448, 112, 452, 610),
|
||||
),
|
||||
)
|
||||
COMBAT_SUPPORT_SELECTED = ButtonWrapper(
|
||||
name='COMBAT_SUPPORT_SELECTED',
|
||||
share=Button(
|
||||
file='./assets/share/combat/support/COMBAT_SUPPORT_SELECTED.png',
|
||||
area=(69, 114, 91, 116),
|
||||
search=(49, 94, 111, 136),
|
||||
color=(254, 254, 254),
|
||||
button=(69, 114, 91, 116),
|
||||
),
|
||||
)
|
@ -3,6 +3,16 @@ from module.base.button import Button, ButtonWrapper
|
||||
# This file was auto-generated, do not modify it manually. To generate:
|
||||
# ``` python -m dev_tools.button_extract ```
|
||||
|
||||
COMBAT_TEAM_DISMISSSUPPORT = ButtonWrapper(
|
||||
name='COMBAT_TEAM_DISMISSSUPPORT',
|
||||
share=Button(
|
||||
file='./assets/share/combat/team/COMBAT_TEAM_DISMISSSUPPORT.png',
|
||||
area=(1127, 477, 1154, 501),
|
||||
search=(1107, 457, 1174, 521),
|
||||
color=(132, 140, 150),
|
||||
button=(1127, 477, 1154, 501),
|
||||
),
|
||||
)
|
||||
COMBAT_TEAM_PREPARE = ButtonWrapper(
|
||||
name='COMBAT_TEAM_PREPARE',
|
||||
cn=Button(
|
||||
@ -13,6 +23,16 @@ COMBAT_TEAM_PREPARE = ButtonWrapper(
|
||||
button=(958, 641, 1193, 676),
|
||||
),
|
||||
)
|
||||
COMBAT_TEAM_SUPPORT = ButtonWrapper(
|
||||
name='COMBAT_TEAM_SUPPORT',
|
||||
share=Button(
|
||||
file='./assets/share/combat/team/COMBAT_TEAM_SUPPORT.png',
|
||||
area=(1123, 477, 1158, 503),
|
||||
search=(1103, 457, 1178, 523),
|
||||
color=(195, 215, 201),
|
||||
button=(1123, 477, 1158, 503),
|
||||
),
|
||||
)
|
||||
TEAM_1 = ButtonWrapper(
|
||||
name='TEAM_1',
|
||||
share=Button(
|
||||
|
@ -3,15 +3,17 @@ from module.logger import logger
|
||||
from tasks.base.assets.assets_base_page import CLOSE
|
||||
from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT
|
||||
from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE
|
||||
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE
|
||||
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE, COMBAT_TEAM_SUPPORT, COMBAT_TEAM_DISMISSSUPPORT
|
||||
from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST
|
||||
from tasks.combat.interact import CombatInteract
|
||||
from tasks.combat.prepare import CombatPrepare
|
||||
from tasks.combat.state import CombatState
|
||||
from tasks.combat.team import CombatTeam
|
||||
from tasks.combat.support import CombatSupport
|
||||
from tasks.map.control.joystick import MapControlJoystick
|
||||
|
||||
|
||||
class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJoystick):
|
||||
class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSupport, MapControlJoystick):
|
||||
def handle_combat_prepare(self):
|
||||
"""
|
||||
Returns:
|
||||
@ -63,10 +65,12 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJ
|
||||
|
||||
return False
|
||||
|
||||
def combat_prepare(self, team=1):
|
||||
def combat_prepare(self, team=1, support_character: str = None):
|
||||
"""
|
||||
Args:
|
||||
team: 1 to 6.
|
||||
skip_first_screenshot:
|
||||
support_character: Support character name
|
||||
|
||||
Returns:
|
||||
bool: True if success to enter combat
|
||||
@ -78,6 +82,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJ
|
||||
"""
|
||||
logger.hr('Combat prepare')
|
||||
skip_first_screenshot = True
|
||||
pre_set_team = bool(support_character)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
@ -89,6 +94,13 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJ
|
||||
return True
|
||||
|
||||
# Click
|
||||
if self.appear(COMBAT_TEAM_SUPPORT) and support_character:
|
||||
if pre_set_team:
|
||||
self.team_set(team)
|
||||
pre_set_team = False
|
||||
continue
|
||||
self.support_set(support_character)
|
||||
continue
|
||||
if self.appear(COMBAT_TEAM_PREPARE, interval=2):
|
||||
self.team_set(team)
|
||||
self.device.click(COMBAT_TEAM_PREPARE)
|
||||
@ -260,7 +272,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJ
|
||||
self.device.click(COMBAT_EXIT)
|
||||
continue
|
||||
|
||||
def combat(self, team: int = 1, wave_limit: int = 0, skip_first_screenshot=True):
|
||||
def combat(self, team: int = 1, wave_limit: int = 0, skip_first_screenshot=True, support_character: str = None):
|
||||
"""
|
||||
Combat until trailblaze power runs out.
|
||||
|
||||
@ -268,6 +280,9 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJ
|
||||
team: 1 to 6.
|
||||
wave_limit: Limit combat runs, 0 means no limit.
|
||||
skip_first_screenshot:
|
||||
use_support: "do_not_use", "always_use", "when_daily"
|
||||
is_daily: True if is a daily task
|
||||
support_character: Support character name
|
||||
|
||||
Returns:
|
||||
bool: True if trailblaze power exhausted
|
||||
@ -287,7 +302,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, MapControlJ
|
||||
logger.hr('Combat', level=2)
|
||||
logger.info(f'Combat, team={team}, wave={self.combat_wave_done}/{self.combat_wave_limit}')
|
||||
# Prepare
|
||||
prepare = self.combat_prepare(team)
|
||||
prepare = self.combat_prepare(team, support_character)
|
||||
if not prepare:
|
||||
self.combat_exit()
|
||||
break
|
||||
|
217
tasks/combat/support.py
Normal file
@ -0,0 +1,217 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
from scipy import signal
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import area_size, crop, rgb2luma, load_image
|
||||
from module.logger import logger
|
||||
from module.ui.scroll import Scroll
|
||||
from tasks.base.ui import UI
|
||||
from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST, \
|
||||
COMBAT_SUPPORT_LIST_SCROLL, COMBAT_SUPPORT_SELECTED
|
||||
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_SUPPORT, COMBAT_TEAM_DISMISSSUPPORT
|
||||
|
||||
|
||||
class SupportCharacter:
|
||||
_image_cache = {}
|
||||
|
||||
def __init__(self, name, screenshot, similarity=0.85):
|
||||
self.name = name
|
||||
self.image = self._scale_character()
|
||||
self.screenshot = screenshot
|
||||
self.similarity = similarity
|
||||
self.button = self._find_character()
|
||||
|
||||
def __bool__(self):
|
||||
# __bool__ is called when use an object of the class in a boolean context
|
||||
return self.button is not None
|
||||
|
||||
def _scale_character(self):
|
||||
"""
|
||||
Returns:
|
||||
Image: Character image after scaled
|
||||
"""
|
||||
|
||||
if self.name in SupportCharacter._image_cache:
|
||||
logger.info(f"Using cached image of {self.name}")
|
||||
return SupportCharacter._image_cache[self.name]
|
||||
|
||||
img = load_image(f"assets/character/{self.name}.png")
|
||||
scaled_img = cv2.resize(img, (85, 82))
|
||||
SupportCharacter._image_cache[self.name] = scaled_img
|
||||
logger.info(f"Character {self.name} image cached")
|
||||
return scaled_img
|
||||
|
||||
def _find_character(self):
|
||||
character = np.array(self.image)
|
||||
support_list_img = self.screenshot
|
||||
res = cv2.matchTemplate(character, support_list_img, cv2.TM_CCOEFF_NORMED)
|
||||
|
||||
_, max_val, _, max_loc = cv2.minMaxLoc(res)
|
||||
|
||||
character_width = character.shape[1]
|
||||
character_height = character.shape[0]
|
||||
|
||||
return (max_loc[0], max_loc[1], max_loc[0] + character_width, max_loc[1] + character_height) \
|
||||
if max_val >= self.similarity else None
|
||||
|
||||
def selected_icon_search(self):
|
||||
"""
|
||||
Returns:
|
||||
tuple: (x1, y1, x2, y2) of selected icon search area
|
||||
"""
|
||||
return (
|
||||
self.button[0], self.button[1] - 5, self.button[0] + 30, self.button[1]) if self.button else None
|
||||
|
||||
|
||||
class SupportListScroll(Scroll):
|
||||
def cal_position(self, main):
|
||||
"""
|
||||
Args:
|
||||
main (ModuleBase):
|
||||
|
||||
Returns:
|
||||
float: 0 to 1.
|
||||
"""
|
||||
image = main.device.image
|
||||
|
||||
temp_area = list(self.area)
|
||||
temp_area[0] = int(temp_area[0] * 0.98)
|
||||
temp_area[2] = int(temp_area[2] * 1.02)
|
||||
|
||||
line = rgb2luma(crop(image, temp_area)).flatten()
|
||||
width = area_size(temp_area)[0]
|
||||
parameters = {
|
||||
"height": 180,
|
||||
"prominence": 30,
|
||||
"distance": width * 0.75,
|
||||
}
|
||||
peaks, _ = signal.find_peaks(line, **parameters)
|
||||
peaks //= width
|
||||
self.length = len(peaks)
|
||||
middle = np.mean(peaks)
|
||||
|
||||
position = (middle - self.length / 2) / (self.total - self.length)
|
||||
position = position if position > 0 else 0.0
|
||||
position = position if position < 1 else 1.0
|
||||
logger.attr(
|
||||
self.name, f"{position:.2f} ({middle}-{self.length / 2})/({self.total}-{self.length})")
|
||||
return position
|
||||
|
||||
|
||||
class CombatSupport(UI):
|
||||
def support_set(self, support_character_name: str = "FirstCharacter"):
|
||||
"""
|
||||
Args:
|
||||
support_character_name: Support character name
|
||||
|
||||
Returns:
|
||||
bool: If clicked
|
||||
|
||||
Pages:
|
||||
in: COMBAT_PREPARE
|
||||
mid: COMBAT_SUPPORT_LIST
|
||||
out: COMBAT_PREPARE
|
||||
"""
|
||||
logger.hr("Combat support")
|
||||
skip_first_screenshot = True
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if self.appear(COMBAT_TEAM_DISMISSSUPPORT):
|
||||
return True
|
||||
|
||||
# Click
|
||||
if self.appear(COMBAT_TEAM_SUPPORT, interval=2):
|
||||
self.device.click(COMBAT_TEAM_SUPPORT)
|
||||
self.interval_reset(COMBAT_TEAM_SUPPORT)
|
||||
continue
|
||||
if self.appear(COMBAT_SUPPORT_LIST, interval=2):
|
||||
if support_character_name != "FirstCharacter":
|
||||
self._search_support(
|
||||
support_character_name) # Search support
|
||||
self.device.click(COMBAT_SUPPORT_ADD)
|
||||
self.interval_reset(COMBAT_SUPPORT_LIST)
|
||||
continue
|
||||
|
||||
def _search_support(self, support_character_name: str = "JingYuan"):
|
||||
"""
|
||||
Args:
|
||||
support_character_name: Support character name
|
||||
|
||||
Returns:
|
||||
bool: True if found support else False
|
||||
|
||||
Pages:
|
||||
in: COMBAT_SUPPORT_LIST
|
||||
out: COMBAT_SUPPORT_LIST
|
||||
"""
|
||||
logger.hr("Combat support search")
|
||||
scroll = SupportListScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area, color=(194, 196, 205),
|
||||
name=COMBAT_SUPPORT_LIST_SCROLL.name)
|
||||
if scroll.appear(main=self):
|
||||
if not scroll.at_bottom(main=self):
|
||||
scroll.set_bottom(main=self)
|
||||
scroll.set_top(main=self)
|
||||
|
||||
logger.info("Searching support")
|
||||
skip_first_screenshot = False
|
||||
character = None
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
if not support_character_name.startswith("Trailblazer"):
|
||||
character = SupportCharacter(support_character_name, self.device.image)
|
||||
else:
|
||||
character = SupportCharacter(f"Stelle{support_character_name[11:]}",
|
||||
self.device.image) or SupportCharacter(
|
||||
f"Caelum{support_character_name[11:]}", self.device.image)
|
||||
|
||||
if character:
|
||||
logger.info("Support found")
|
||||
if self._select_support(character):
|
||||
return True
|
||||
else:
|
||||
logger.warning("Support not selected")
|
||||
return False
|
||||
|
||||
if not scroll.at_bottom(main=self):
|
||||
scroll.next_page(main=self)
|
||||
continue
|
||||
else:
|
||||
logger.info("Support not found")
|
||||
return False
|
||||
|
||||
def _select_support(self, character: SupportCharacter):
|
||||
"""
|
||||
Args:
|
||||
character: Support character
|
||||
|
||||
Pages:
|
||||
in: COMBAT_SUPPORT_LIST
|
||||
out: COMBAT_SUPPORT_LIST
|
||||
"""
|
||||
logger.hr("Combat support select")
|
||||
COMBAT_SUPPORT_SELECTED.matched_button.search = character.selected_icon_search()
|
||||
skip_first_screenshot = False
|
||||
interval = Timer(2)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if self.match_template(COMBAT_SUPPORT_SELECTED):
|
||||
return True
|
||||
|
||||
if interval.reached():
|
||||
self.device.click(character)
|
||||
interval.reset()
|
||||
continue
|
@ -7,11 +7,16 @@ from tasks.dungeon.ui import DungeonUI
|
||||
|
||||
|
||||
class Dungeon(DungeonUI, DungeonEvent, Combat):
|
||||
def run(self, dungeon: DungeonList = None, team: int = None):
|
||||
def run(self, dungeon: DungeonList = None, team: int = None, use_support: str = None, is_daily: bool = False,
|
||||
support_character: str = None):
|
||||
if dungeon is None:
|
||||
dungeon = DungeonList.find(self.config.Dungeon_Name)
|
||||
if team is None:
|
||||
team = self.config.Dungeon_Team
|
||||
if use_support is None:
|
||||
use_support = self.config.Dungeon_Support
|
||||
if support_character is None:
|
||||
support_character = self.config.Dungeon_SupportCharacter if use_support == "always_use" or use_support == "when_daily" and is_daily else None
|
||||
|
||||
# UI switches
|
||||
switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
||||
@ -26,7 +31,7 @@ class Dungeon(DungeonUI, DungeonEvent, Combat):
|
||||
self._dungeon_nav_goto(calyx)
|
||||
if remain := self.get_double_event_remain():
|
||||
self.dungeon_goto(calyx)
|
||||
if self.combat(team, wave_limit=remain):
|
||||
if self.combat(team, wave_limit=remain, support_character=support_character):
|
||||
self.delay_dungeon_task(calyx)
|
||||
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
||||
|
||||
@ -38,7 +43,7 @@ class Dungeon(DungeonUI, DungeonEvent, Combat):
|
||||
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
||||
self.dungeon_goto(dungeon)
|
||||
|
||||
self.combat(team)
|
||||
self.combat(team=team, support_character=support_character)
|
||||
self.delay_dungeon_task(dungeon)
|
||||
|
||||
def delay_dungeon_task(self, dungeon):
|
||||
|