StarRailCopilot/tasks/rogue/blessing/curio.py

167 lines
5.9 KiB
Python
Raw Normal View History

2023-08-12 07:15:25 +00:00
import re
import numpy as np
from module.base.filter import MultiLangFilter
2023-08-12 07:15:25 +00:00
from module.base.timer import Timer
from module.base.utils import area_offset, area_pad
2023-08-12 07:15:25 +00:00
from module.logger import logger
from module.ocr.ocr import Ocr, OcrResultButton
from tasks.rogue.assets.assets_rogue_curio import CURIO_ENFORCE, OCR_ROGUE_CURIO, CURIO_SELECTED
from tasks.rogue.assets.assets_rogue_ui import BLESSING_CONFIRM, BLESSING_ENHANCED, BLESSING_LOST, BLESSING_OBTAINED
from tasks.rogue.blessing.preset import CURIO_PRESET
2023-12-18 16:53:33 +00:00
from tasks.rogue.blessing.selector import RogueSelector
from tasks.rogue.blessing.utils import get_regex_from_keyword_name, parse_name
2023-10-05 10:52:55 +00:00
from tasks.rogue.keywords import RogueCurio
CURIO_FILTER_ATTR = tuple()
CURIO_ATTR_NAME = 'curio_name'
2023-09-10 16:38:32 +00:00
patt = get_regex_from_keyword_name(RogueCurio, CURIO_ATTR_NAME)
CURIO_FILTER_ATTR += (CURIO_ATTR_NAME,)
2023-08-22 19:00:45 +00:00
CURIO_FILTER_PRESET = ('random', 'unrecorded')
2023-09-10 16:38:32 +00:00
FILTER_REGEX = re.compile(patt)
CURIO_FILTER = MultiLangFilter(FILTER_REGEX, CURIO_FILTER_ATTR, CURIO_FILTER_PRESET)
2023-08-12 07:15:25 +00:00
class RogueCurioOcr(Ocr):
merge_thres_y = 40
2023-08-12 07:15:25 +00:00
def after_process(self, result):
result = super().after_process(result)
2023-09-12 10:39:23 +00:00
if self.lang == 'cn':
2023-08-12 07:15:25 +00:00
replace_pattern_dict = {
"": "",
2023-08-14 20:16:31 +00:00
"漂灭": "湮灭",
2023-09-10 16:38:32 +00:00
"殷子": "骰子",
2023-08-12 07:15:25 +00:00
}
for pattern, replace in replace_pattern_dict.items():
result = re.sub(pattern, replace, result)
return result
class RogueCurioSelector(RogueSelector):
def recognition(self):
self.ocr_results = []
2023-08-12 07:15:25 +00:00
ocr = RogueCurioOcr(OCR_ROGUE_CURIO)
results = ocr.matched_ocr(self.main.device.image, RogueCurio)
2023-08-12 07:15:25 +00:00
expect_num = 3
if len(results) != expect_num:
logger.warning(f"The OCR result does not match the curio count. "
f"Expect {expect_num}, but recognized {len(results)} only.")
self.ocr_results = results
2023-08-12 07:15:25 +00:00
return results
def ui_select(self, target: OcrResultButton | None, skip_first_screenshot=True):
2023-08-12 07:15:25 +00:00
def is_curio_selected():
CURIO_SELECTED.matched_button.search = area_pad(area_offset(target.area, (0, -50)), -50)
return self.main.appear(CURIO_SELECTED)
2023-08-12 07:15:25 +00:00
def is_select_curio_complete():
"""
Case 1: back to main page
2023-08-14 20:16:31 +00:00
Case 2: event page
Case 3: is_page_choose_blessing()
Case 4: BLESSING_ENHANCED
Case 5: BLESSING_OBTAINED
Case 6: BLESSING_LOST
2023-08-12 07:15:25 +00:00
"""
if self.main.is_in_main():
logger.info("Main page checked")
return True
if self.main.is_page_event():
logger.info("Event page checked")
return True
if self.main.is_page_choose_blessing():
logger.info("is_page_choose_blessing() checked")
return True
if self.main.appear(BLESSING_ENHANCED):
logger.info("BLESSING_ENHANCED checked")
return True
if self.main.appear(BLESSING_OBTAINED):
logger.info("BLESSING_OBTAINED checked")
return True
if self.main.appear(BLESSING_LOST):
logger.info("BLESSING_LOST checked")
return True
return False
2023-08-12 07:15:25 +00:00
enforce = False
if not target:
enforce = True
2023-08-12 07:15:25 +00:00
interval = Timer(1)
# start -> selected
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.main.device.screenshot()
2023-08-12 07:15:25 +00:00
if is_curio_selected():
if enforce:
logger.info("Curio selected (enforce)")
else:
logger.info(f"Curio {target} selected")
2023-08-12 07:15:25 +00:00
break
if interval.reached():
if enforce:
self.main.device.click(CURIO_ENFORCE)
2023-08-12 07:15:25 +00:00
else:
self.main.device.click(target)
2023-08-12 07:15:25 +00:00
interval.reset()
skip_first_screenshot = True
# Avoid double-clicking
interval = Timer(3, count=6)
2023-08-12 07:15:25 +00:00
# selected -> confirm
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.main.device.screenshot()
2023-08-12 07:15:25 +00:00
if is_select_curio_complete():
break
2023-10-19 02:06:31 +00:00
if self.main.handle_popup_confirm():
continue
2023-08-12 07:15:25 +00:00
if interval.reached():
self.main.device.click(BLESSING_CONFIRM)
2023-08-12 07:15:25 +00:00
interval.reset()
def try_select(self, option: OcrResultButton | str):
if option == 'random':
target = np.random.choice(self.ocr_results)
self.ui_select(target)
return True
2023-08-22 19:00:45 +00:00
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
return False
def load_filter(self):
filter_ = CURIO_FILTER
2023-08-22 19:00:45 +00:00
string = ""
2023-12-18 15:30:48 +00:00
match self.main.config.RogueBlessing_PresetCurioFilter:
case 'preset':
string = CURIO_PRESET[self.main.config.RogueWorld_Path]
2023-08-22 19:00:45 +00:00
case 'custom':
2023-12-18 15:30:48 +00:00
string = self.main.config.RogueBlessing_CustomCurioFilter
2023-08-22 19:00:45 +00:00
string = parse_name(string)
2023-12-18 15:30:48 +00:00
if not string.endswith('random'):
string += '> random'
match self.main.config.RogueBlessing_SelectionStrategy:
2023-08-22 19:00:45 +00:00
case 'unrecorded-first':
string = 'unrecorded > ' + string
case 'before-random':
string = string.replace('random', 'unrecorded > random')
filter_.load(string)
self.filter_ = filter_