diff --git a/assets/share/rogue/ui/FLAG_UNRECORD.png b/assets/share/rogue/ui/FLAG_UNRECORD.png new file mode 100644 index 000000000..40e34f265 Binary files /dev/null and b/assets/share/rogue/ui/FLAG_UNRECORD.png differ diff --git a/config/template.json b/config/template.json index 719947ec8..39cd0e0c6 100644 --- a/config/template.json +++ b/config/template.json @@ -90,10 +90,13 @@ "Bonus": "Blessing Cosmos", "PresetResonanceFilter": "preset-1", "CustomResonanceFilter": "回响构音:均晶转变 > 回响构音:零维强化\n> 回响构音:第二次初恋 > 回响构音:体验的富翁\n> 回响构音:局外人 > 回响构音:怀疑的四重根\n> 回响构音:诸法无我 > 回响构音:诸行无常\n> 回响构音:射不主皮 > 回响构音:柘弓危矢\n> 回响构音:激变变星 > 回响构音:极端氦闪\n> 回响构音:末日狂欢 > 回响构音:树苗长高舞", + "ResonanceSelectionStrategy": "follow-presets", "PresetBlessingFilter": "preset-1", "CustomBlessingFilter": "巡猎-3 > 《冠军晚餐·猫的摇篮》 > 丰饶众生,一法界心 > 毁灭-3 \n> 火堆外的夜 > 巡猎-2 > 毁灭-2 > 巡猎 > reset > random", + "BlessingSelectionStrategy": "follow-presets", "PresetCurioFilter": "preset-1", - "CustomCurioFilter": "博士之袍 > 福灵胶 > 分裂金币 > 信仰债券 > 换境桂冠 > 俱乐部券 > 碎星芳饵 > random" + "CustomCurioFilter": "博士之袍 > 福灵胶 > 分裂金币 > 信仰债券 > 换境桂冠 > 俱乐部券 > 碎星芳饵 > random", + "CurioSelectionStrategy": "follow-presets" } } } \ No newline at end of file diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 361872936..d1b967a22 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -490,6 +490,15 @@ "type": "textarea", "value": "回响构音:均晶转变 > 回响构音:零维强化\n> 回响构音:第二次初恋 > 回响构音:体验的富翁\n> 回响构音:局外人 > 回响构音:怀疑的四重根\n> 回响构音:诸法无我 > 回响构音:诸行无常\n> 回响构音:射不主皮 > 回响构音:柘弓危矢\n> 回响构音:激变变星 > 回响构音:极端氦闪\n> 回响构音:末日狂欢 > 回响构音:树苗长高舞" }, + "ResonanceSelectionStrategy": { + "type": "select", + "value": "follow-presets", + "option": [ + "follow-presets", + "unrecorded-first", + "before-random" + ] + }, "PresetBlessingFilter": { "type": "select", "value": "preset-1", @@ -502,6 +511,15 @@ "type": "textarea", "value": "巡猎-3 > 《冠军晚餐·猫的摇篮》 > 丰饶众生,一法界心 > 毁灭-3 \n> 火堆外的夜 > 巡猎-2 > 毁灭-2 > 巡猎 > reset > random" }, + "BlessingSelectionStrategy": { + "type": "select", + "value": "follow-presets", + "option": [ + "follow-presets", + "unrecorded-first", + "before-random" + ] + }, "PresetCurioFilter": { "type": "select", "value": "preset-1", @@ -513,6 +531,15 @@ "CustomCurioFilter": { "type": "textarea", "value": "博士之袍 > 福灵胶 > 分裂金币 > 信仰债券 > 换境桂冠 > 俱乐部券 > 碎星芳饵 > random" + }, + "CurioSelectionStrategy": { + "type": "select", + "value": "follow-presets", + "option": [ + "follow-presets", + "unrecorded-first", + "before-random" + ] } } } diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index a8c495859..29eedfe0b 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -127,14 +127,24 @@ Rogue: > 回响构音:射不主皮 > 回响构音:柘弓危矢 > 回响构音:激变变星 > 回响构音:极端氦闪 > 回响构音:末日狂欢 > 回响构音:树苗长高舞 + ResonanceSelectionStrategy: + value: follow-presets + option: [ follow-presets, unrecorded-first, before-random ] PresetBlessingFilter: value: preset-1 option: [ preset-1, custom ] CustomBlessingFilter: |- 巡猎-3 > 《冠军晚餐·猫的摇篮》 > 丰饶众生,一法界心 > 毁灭-3 > 火堆外的夜 > 巡猎-2 > 毁灭-2 > 巡猎 > reset > random + BlessingSelectionStrategy: + value: follow-presets + option: [ follow-presets, unrecorded-first, before-random ] PresetCurioFilter: value: preset-1 option: [ preset-1, custom ] CustomCurioFilter: |- 博士之袍 > 福灵胶 > 分裂金币 > 信仰债券 > 换境桂冠 > 俱乐部券 > 碎星芳饵 > random + CurioSelectionStrategy: + value: follow-presets + option: [ follow-presets, unrecorded-first, before-random ] + diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 55f8f189c..7af5928c2 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -57,7 +57,10 @@ class GeneratedConfig: Rogue_Bonus = 'Blessing Cosmos' # Blessing Cosmos, Miracle Cosmos, Fragmented Cosmos Rogue_PresetResonanceFilter = 'preset-1' # preset-1, custom Rogue_CustomResonanceFilter = '回响构音:均晶转变 > 回响构音:零维强化\n> 回响构音:第二次初恋 > 回响构音:体验的富翁\n> 回响构音:局外人 > 回响构音:怀疑的四重根\n> 回响构音:诸法无我 > 回响构音:诸行无常\n> 回响构音:射不主皮 > 回响构音:柘弓危矢\n> 回响构音:激变变星 > 回响构音:极端氦闪\n> 回响构音:末日狂欢 > 回响构音:树苗长高舞' + Rogue_ResonanceSelectionStrategy = 'follow-presets' # follow-presets, unrecorded-first, before-random Rogue_PresetBlessingFilter = 'preset-1' # preset-1, custom Rogue_CustomBlessingFilter = '巡猎-3 > 《冠军晚餐·猫的摇篮》 > 丰饶众生,一法界心 > 毁灭-3 \n> 火堆外的夜 > 巡猎-2 > 毁灭-2 > 巡猎 > reset > random' + Rogue_BlessingSelectionStrategy = 'follow-presets' # follow-presets, unrecorded-first, before-random Rogue_PresetCurioFilter = 'preset-1' # preset-1, custom Rogue_CustomCurioFilter = '博士之袍 > 福灵胶 > 分裂金币 > 信仰债券 > 换境桂冠 > 俱乐部券 > 碎星芳饵 > random' + Rogue_CurioSelectionStrategy = 'follow-presets' # follow-presets, unrecorded-first, before-random diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 92d8207f3..d95753206 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -400,6 +400,13 @@ "name": "Custom Resonance Filter", "help": "" }, + "ResonanceSelectionStrategy": { + "name": "Resonance Selection Strategy", + "help": "", + "follow-presets": "Follow presets", + "unrecorded-first": "Choose index locked resonance first", + "before-random": "Follow presets, but choose index locked one first when filter goes to randomly choose" + }, "PresetBlessingFilter": { "name": "Preset Blessing Filter", "help": "", @@ -410,6 +417,13 @@ "name": "Custom Blessing Filter", "help": "" }, + "BlessingSelectionStrategy": { + "name": "Blessing jSelection Strategy", + "help": "", + "follow-presets": "Follow presets", + "unrecorded-first": "Choose index locked blessing first", + "before-random": "Follow presets, but choose index locked one first when filter goes to randomly choose" + }, "PresetCurioFilter": { "name": "Preset Curio Filter", "help": "", @@ -419,6 +433,13 @@ "CustomCurioFilter": { "name": "Custom Curio Filter", "help": "" + }, + "CurioSelectionStrategy": { + "name": "Curio Selection Strategy", + "help": "", + "follow-presets": "Follow presets", + "unrecorded-first": "Choose index locked curio first", + "before-random": "Follow presets, but choose index locked one first when filter goes to randomly choose" } }, "Gui": { diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index ab58cde1f..ce4740795 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -400,6 +400,13 @@ "name": "Rogue.CustomResonanceFilter.name", "help": "Rogue.CustomResonanceFilter.help" }, + "ResonanceSelectionStrategy": { + "name": "Rogue.ResonanceSelectionStrategy.name", + "help": "Rogue.ResonanceSelectionStrategy.help", + "follow-presets": "follow-presets", + "unrecorded-first": "unrecorded-first", + "before-random": "before-random" + }, "PresetBlessingFilter": { "name": "Rogue.PresetBlessingFilter.name", "help": "Rogue.PresetBlessingFilter.help", @@ -410,6 +417,13 @@ "name": "Rogue.CustomBlessingFilter.name", "help": "Rogue.CustomBlessingFilter.help" }, + "BlessingSelectionStrategy": { + "name": "Rogue.BlessingSelectionStrategy.name", + "help": "Rogue.BlessingSelectionStrategy.help", + "follow-presets": "follow-presets", + "unrecorded-first": "unrecorded-first", + "before-random": "before-random" + }, "PresetCurioFilter": { "name": "Rogue.PresetCurioFilter.name", "help": "Rogue.PresetCurioFilter.help", @@ -419,6 +433,13 @@ "CustomCurioFilter": { "name": "Rogue.CustomCurioFilter.name", "help": "Rogue.CustomCurioFilter.help" + }, + "CurioSelectionStrategy": { + "name": "Rogue.CurioSelectionStrategy.name", + "help": "Rogue.CurioSelectionStrategy.help", + "follow-presets": "follow-presets", + "unrecorded-first": "unrecorded-first", + "before-random": "before-random" } }, "Gui": { diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 58151e042..9ffe63e2b 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -391,15 +391,22 @@ "Fragmented Cosmos": "破碎宇宙(获得宇宙碎片)" }, "PresetResonanceFilter": { - "name": "命途回响过滤器", + "name": "回响构音过滤器", "help": "", "preset-1": "预设 1", "custom": "自定义" }, "CustomResonanceFilter": { - "name": "自定义命途回响过滤器", + "name": "自定义回响构音过滤器", "help": "" }, + "ResonanceSelectionStrategy": { + "name": "回响构音选择策略", + "help": "", + "follow-presets": "遵循预设", + "unrecorded-first": "优先选择图鉴未解锁的回响构音", + "before-random": "遵循预设,但选择\"图鉴未解锁\"的优先级高于\"随机选择\"" + }, "PresetBlessingFilter": { "name": "祝福过滤器", "help": "", @@ -410,6 +417,13 @@ "name": "自定义祝福过滤器", "help": "" }, + "BlessingSelectionStrategy": { + "name": "祝福选择策略", + "help": "", + "follow-presets": "遵循预设", + "unrecorded-first": "优先选择图鉴未解锁的祝福", + "before-random": "遵循预设,但选择\"图鉴未解锁\"的优先级高于\"随机选择\"" + }, "PresetCurioFilter": { "name": "奇物过滤器", "help": "", @@ -419,6 +433,13 @@ "CustomCurioFilter": { "name": "自定义祝福过滤器", "help": "" + }, + "CurioSelectionStrategy": { + "name": "奇物选择策略", + "help": "", + "follow-presets": "遵循预设", + "unrecorded-first": "优先选择图鉴未解锁的奇物", + "before-random": "遵循预设,但选择\"图鉴未解锁\"的优先级高于\"随机选择\"" } }, "Gui": { diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 52b5f15f0..00e90cc18 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -391,15 +391,22 @@ "Fragmented Cosmos": "破碎宇宙(獲得宇宙碎片)" }, "PresetResonanceFilter": { - "name": "命途迴響过滤器", + "name": "迴響構音过滤器", "help": "", "preset-1": "預設 1", "custom": "自訂" }, "CustomResonanceFilter": { - "name": "自訂命途迴響过滤器", + "name": "自訂迴響構音过滤器", "help": "" }, + "ResonanceSelectionStrategy": { + "name": "迴響構音選擇策略", + "help": "", + "follow-presets": "遵循預設", + "unrecorded-first": "優先選擇圖鑑未解鎖的迴響構音", + "before-random": "遵循預設,但選擇\"圖鑑未解鎖\"的優先級高於\"隨機選擇\"" + }, "PresetBlessingFilter": { "name": "祝福过滤器", "help": "", @@ -410,6 +417,13 @@ "name": "自訂祝福过滤器", "help": "" }, + "BlessingSelectionStrategy": { + "name": "祝福選擇策略", + "help": "", + "follow-presets": "遵循預設", + "unrecorded-first": "優先選擇圖鑑未解鎖的祝福", + "before-random": "遵循預設,但選擇\"圖鑑未解鎖\"的優先級高於\"隨機選擇\"" + }, "PresetCurioFilter": { "name": "奇物过滤器", "help": "", @@ -419,6 +433,13 @@ "CustomCurioFilter": { "name": "自訂奇物过滤器", "help": "" + }, + "CurioSelectionStrategy": { + "name": "奇物選擇策略", + "help": "", + "follow-presets": "遵循預設", + "unrecorded-first": "優先選擇圖鑑未解鎖的奇物", + "before-random": "遵循預設,但選擇\"圖鑑未解鎖\"的優先級高於\"隨機選擇\"" } }, "Gui": { diff --git a/tasks/rogue/assets/assets_rogue_ui.py b/tasks/rogue/assets/assets_rogue_ui.py index 6eccc8144..9a2001e83 100644 --- a/tasks/rogue/assets/assets_rogue_ui.py +++ b/tasks/rogue/assets/assets_rogue_ui.py @@ -33,6 +33,16 @@ COSMIC_FRAGMENT = ButtonWrapper( button=(1146, 19, 1181, 55), ), ) +FLAG_UNRECORD = ButtonWrapper( + name='FLAG_UNRECORD', + share=Button( + file='./assets/share/rogue/ui/FLAG_UNRECORD.png', + area=(746, 149, 778, 181), + search=(726, 129, 798, 201), + color=(133, 130, 161), + button=(746, 149, 778, 181), + ), +) OCR_COSMIC_FRAGMENT = ButtonWrapper( name='OCR_COSMIC_FRAGMENT', share=Button( diff --git a/tasks/rogue/blessing.py b/tasks/rogue/blessing.py index b6719b67f..5ee1f13cb 100644 --- a/tasks/rogue/blessing.py +++ b/tasks/rogue/blessing.py @@ -43,7 +43,7 @@ pattern += enhancement_regex BLESSING_FILTER_ATTR += (ENHANCEMENT_ATTR_NAME,) FILETER_REGEX = re.compile(pattern) -BLESSING_FILTER_PRESET = ("reset", "random") +BLESSING_FILTER_PRESET = ("reset", "random", "unrecorded") BLESSING_FILTER = MultiLangFilter(FILETER_REGEX, BLESSING_FILTER_ATTR, BLESSING_FILTER_PRESET) # resonance filter @@ -51,12 +51,13 @@ RESONANCE_ATTR_NAME = 'resonance_name' pattern = get_regex_from_keyword_name(RogueResonance, RESONANCE_ATTR_NAME) FILETER_REGEX = re.compile(pattern) -RESONANCE_FILTER_PRESET = ("random",) +RESONANCE_FILTER_PRESET = ("random", "unrecorded") RESONANCE_FILTER = MultiLangFilter(FILETER_REGEX, (RESONANCE_ATTR_NAME,), RESONANCE_FILTER_PRESET) class RogueBuffOcr(Ocr): - merge_thres_y = 40 + merge_thres_x = 40 + merge_thres_y = 20 def after_process(self, result): result = super().after_process(result) @@ -64,9 +65,9 @@ class RogueBuffOcr(Ocr): replace_pattern_dict = { "蓬失": "蓬矢", "柘弓危失": "柘弓危矢", - "飞虹凿齿": "飞虹诛凿齿", + "飞虹珠?凿?齿": "飞虹诛凿齿", "天培步危": "天棓步危", - "云[摘销]?逐步离": "云镝逐步离", + "云[摘销锅]?逐步离": "云镝逐步离", "制桑": "制穹桑", "乌号基": "乌号綦", "追摩物": "追孽物", @@ -83,7 +84,7 @@ class RogueBuffOcr(Ocr): "虚安供品": "虚妄供品", "原初的苦$": "原初的苦衷", "厌离邪苦": "厌离邪秽苦", - r".*繁.*": "葳蕤繁祉,延彼遐龄" + r".*繁.*": "葳蕤繁祉,延彼遐龄", } for pat, replace in replace_pattern_dict.items(): result = re.sub(pat, replace, result) @@ -257,20 +258,45 @@ class RogueBlessingSelector(RogueSelector): return True def load_filter(self): - filter_ = None keyword = self.ocr_results[0].matched_keyword - if isinstance(keyword, RogueBlessing): - filter_ = BLESSING_FILTER - if self.main.config.Rogue_PresetBlessingFilter == 'preset-1': - filter_.load(parse_name(BLESSING_PRESET_1)) - if self.main.config.Rogue_PresetBlessingFilter == 'custom': - filter_.load(parse_name(self.main.config.Rogue_CustomBlessingFilter)) - if isinstance(keyword, RogueResonance): - filter_ = RESONANCE_FILTER - if self.main.config.Rogue_PresetResonanceFilter == 'preset-1': - RESONANCE_FILTER.load(parse_name(RESONANCE_PRESET_1)) - if self.main.config.Rogue_PresetResonanceFilter == 'custom': - RESONANCE_FILTER.load(parse_name(self.main.config.Rogue_CustomResonanceFilter)) + if not isinstance(keyword, (RogueBlessing, RogueResonance)): + return + filter_configs = { + RogueBlessing: { + "filter_": BLESSING_FILTER, + "preset_config": self.main.config.Rogue_PresetBlessingFilter, + "strategy_config": self.main.config.Rogue_BlessingSelectionStrategy, + "preset_values": { + 'preset-1': BLESSING_PRESET_1, + 'custom': self.main.config.Rogue_CustomBlessingFilter + }, + }, + RogueResonance: { + "filter_": RESONANCE_FILTER, + "preset_config": self.main.config.Rogue_PresetResonanceFilter, + "strategy_config": self.main.config.Rogue_ResonanceSelectionStrategy, + "preset_values": { + 'preset-1': RESONANCE_PRESET_1, + 'custom': self.main.config.Rogue_PresetResonanceFilter, + }, + } + } + # preset + config = filter_configs[type(keyword)] + filter_ = config['filter_'] + preset_config = config['preset_config'] + preset_values = config['preset_values'] + string = preset_values[preset_config] + string = parse_name(string) + + # strategy + strategy_config = config['strategy_config'] + if strategy_config == 'unrecorded-first': + string = "unrecorded > " + string + if strategy_config == 'before-random': + string = string.replace('random', 'unrecorded > random') + + filter_.load(string) self.filter_ = filter_ def try_select(self, option: OcrResultButton | str): @@ -283,6 +309,12 @@ class RogueBlessingSelector(RogueSelector): choose = np.random.choice(self.ocr_results) self.ui_select(choose) return True + if option.lower() == 'unrecorded': + for result in self.ocr_results: + if self.main.is_unrecorded(result, (0, -720, 300, 0)): + self.ui_select(result) + return True + return False if isinstance(option, OcrResultButton): self.ui_select(option) diff --git a/tasks/rogue/curio.py b/tasks/rogue/curio.py index ad4ef61f0..6f0062724 100644 --- a/tasks/rogue/curio.py +++ b/tasks/rogue/curio.py @@ -18,7 +18,7 @@ CURIO_FILTER_ATTR = tuple() CURIO_ATTR_NAME = 'curio_name' pattern = get_regex_from_keyword_name(RogueCurio, CURIO_ATTR_NAME) CURIO_FILTER_ATTR += (CURIO_ATTR_NAME,) -CURIO_FILTER_PRESET = ('random',) +CURIO_FILTER_PRESET = ('random', 'unrecorded') FILTER_REGEX = re.compile(pattern) CURIO_FILTER = MultiLangFilter(FILTER_REGEX, CURIO_FILTER_ATTR, CURIO_FILTER_PRESET) @@ -104,6 +104,13 @@ class RogueCurioSelector(RogueSelector): target = np.random.choice(self.ocr_results) self.ui_select(target) return True + if option == 'unrecorded': + for result in self.ocr_results: + if self.main.is_unrecorded(result, (0, -720, 300, 0)): + self.ui_select(result) + return True + return False + if isinstance(option, OcrResultButton): self.ui_select(option) return True @@ -111,8 +118,19 @@ class RogueCurioSelector(RogueSelector): def load_filter(self): filter_ = CURIO_FILTER - if self.main.config.Rogue_PresetCurioFilter == 'preset-1': - filter_.load(parse_name(CURIO_PRESET_1)) - if self.main.config.Rogue_PresetCurioFilter == 'custom': - filter_.load(parse_name(self.main.config.Rogue_CustomCurioFilter)) + string = "" + match self.main.config.Rogue_PresetCurioFilter: + case 'preset-1': + string = CURIO_PRESET_1 + case 'custom': + string = self.main.config.Rogue_CustomCurioFilter + string = parse_name(string) + + match self.main.config.Rogue_CurioSelectionStrategy: + case 'unrecorded-first': + string = 'unrecorded > ' + string + case 'before-random': + string = string.replace('random', 'unrecorded > random') + + filter_.load(string) self.filter_ = filter_ diff --git a/tasks/rogue/ui.py b/tasks/rogue/ui.py index 4bf4ee8ec..a3df88f9b 100644 --- a/tasks/rogue/ui.py +++ b/tasks/rogue/ui.py @@ -1,6 +1,7 @@ import re -from module.ocr.ocr import Digit, Ocr +from module.base.utils import area_offset +from module.ocr.ocr import Digit, Ocr, OcrResultButton from tasks.base.ui import UI from tasks.rogue.assets.assets_rogue_ui import * from tasks.rogue.keywords import * @@ -42,3 +43,10 @@ class RogueUI(UI): def is_page_event(self): return self.appear(PAGE_EVENT) + + def is_unrecorded(self, target: OcrResultButton, relative_area): + """ + To check a rogue keyword is not record in game index by finding template + """ + FLAG_UNRECORD.matched_button.search = area_offset(relative_area, target.area[:2]) + return self.appear(FLAG_UNRECORD)