mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-25 10:01:10 +00:00
Fix: No kids as low camera height may miss enemy aim icon
This commit is contained in:
parent
0f11911e5c
commit
21307e209e
@ -8,6 +8,7 @@ from hashlib import md5
|
|||||||
|
|
||||||
from module.base.code_generator import CodeGenerator
|
from module.base.code_generator import CodeGenerator
|
||||||
from module.config.utils import deep_get, read_file
|
from module.config.utils import deep_get, read_file
|
||||||
|
from module.exception import ScriptError
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
|
|
||||||
UI_LANGUAGES = ['cn', 'cht', 'en', 'jp', 'es']
|
UI_LANGUAGES = ['cn', 'cht', 'en', 'jp', 'es']
|
||||||
@ -38,15 +39,24 @@ def blessing_name(name: str) -> str:
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
nickname_count = 0
|
|
||||||
|
|
||||||
|
|
||||||
def character_name(name: str) -> str:
|
def character_name(name: str) -> str:
|
||||||
name = text_to_variable(name)
|
name = text_to_variable(name)
|
||||||
name = re.sub('_', '', name)
|
name = re.sub('_', '', name)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def convert_inner_character_to_keyword(name):
|
||||||
|
convert_dict = {
|
||||||
|
'Silwolf': 'SilverWolf',
|
||||||
|
'Klara': 'Clara',
|
||||||
|
'Mar_7th': 'March7th',
|
||||||
|
'PlayerGirl': 'TrailblazerFemale',
|
||||||
|
'PlayerBoy': 'TrailblazerMale',
|
||||||
|
'Ren': 'Blade',
|
||||||
|
}
|
||||||
|
return convert_dict.get(name, name)
|
||||||
|
|
||||||
|
|
||||||
class TextMap:
|
class TextMap:
|
||||||
DATA_FOLDER = ''
|
DATA_FOLDER = ''
|
||||||
|
|
||||||
@ -381,6 +391,30 @@ class KeywordExtract:
|
|||||||
self.load_character_name_keywords()
|
self.load_character_name_keywords()
|
||||||
self.write_keywords(keyword_class='CharacterList', output_file='./tasks/character/keywords/character_list.py',
|
self.write_keywords(keyword_class='CharacterList', output_file='./tasks/character/keywords/character_list.py',
|
||||||
text_convert=character_name)
|
text_convert=character_name)
|
||||||
|
# Generate character height
|
||||||
|
characters = read_file(os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', 'FreeStyleCharacterConfig.json'))
|
||||||
|
regex = re.compile(r'NPC_Avatar_(?P<height>.*?)_(?P<character>.*?)_00')
|
||||||
|
gen = CodeGenerator()
|
||||||
|
dict_height = {}
|
||||||
|
height_index = ['Kid', 'Girl', 'Boy', 'Maid', 'Miss', 'Lady', 'Lad', 'Male']
|
||||||
|
for key in characters.keys():
|
||||||
|
if res := regex.search(key):
|
||||||
|
character, height = res.group('character'), res.group('height')
|
||||||
|
if height not in height_index:
|
||||||
|
continue
|
||||||
|
dict_height[character] = height
|
||||||
|
dict_height = {k: v for k, v in sorted(dict_height.items(), key=lambda item: height_index.index(item[1]))}
|
||||||
|
from tasks.character.keywords.classes import CharacterList
|
||||||
|
with gen.Dict('CHARACTER_HEIGHT'):
|
||||||
|
for character, height in dict_height.items():
|
||||||
|
character = convert_inner_character_to_keyword(character)
|
||||||
|
try:
|
||||||
|
CharacterList.find_name(character)
|
||||||
|
except ScriptError:
|
||||||
|
print(f'Character height data {character} is not defined')
|
||||||
|
continue
|
||||||
|
gen.DictItem(key=character, value=height)
|
||||||
|
gen.write('./tasks/character/keywords/height.py')
|
||||||
|
|
||||||
def generate_battle_pass_quests(self):
|
def generate_battle_pass_quests(self):
|
||||||
battle_pass_quests = read_file(os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', 'BattlePassConfig.json'))
|
battle_pass_quests = read_file(os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', 'BattlePassConfig.json'))
|
||||||
|
@ -180,3 +180,24 @@ class Keyword:
|
|||||||
|
|
||||||
# Not found
|
# Not found
|
||||||
raise ScriptError(f'Cannot find a {cls.__name__} instance that matches "{name}"')
|
raise ScriptError(f'Cannot find a {cls.__name__} instance that matches "{name}"')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_name(cls, name):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
name: Attribute name of keyword.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Keyword instance.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ScriptError: If nothing found.
|
||||||
|
"""
|
||||||
|
if isinstance(name, Keyword):
|
||||||
|
return name
|
||||||
|
for instance in cls.instances.values():
|
||||||
|
if name == instance.name:
|
||||||
|
return instance
|
||||||
|
|
||||||
|
# Not found
|
||||||
|
raise ScriptError(f'Cannot find a {cls.__name__} instance that matches "{name}"')
|
||||||
|
@ -9,9 +9,19 @@ from module.ocr.keyword import Keyword
|
|||||||
class CharacterList(Keyword):
|
class CharacterList(Keyword):
|
||||||
instances: ClassVar = {}
|
instances: ClassVar = {}
|
||||||
|
|
||||||
|
def __hash__(self) -> int:
|
||||||
|
return super().__hash__()
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def is_trailblazer(self) -> bool:
|
def is_trailblazer(self) -> bool:
|
||||||
return 'Trailblazer' in self.name
|
return 'Trailblazer' in self.name
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
@cached_property
|
||||||
return super().__hash__()
|
def height(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns:
|
||||||
|
str: Character height, from list ['Kid', 'Girl', 'Boy', 'Maid', 'Miss', 'Lady', 'Lad', 'Male']
|
||||||
|
or 'Unknown' if no data
|
||||||
|
"""
|
||||||
|
from tasks.character.keywords.height import CHARACTER_HEIGHT
|
||||||
|
return CHARACTER_HEIGHT.get(self.name, 'Unknown')
|
||||||
|
31
tasks/character/keywords/height.py
Normal file
31
tasks/character/keywords/height.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
CHARACTER_HEIGHT = {
|
||||||
|
'Hook': 'Kid',
|
||||||
|
'Bailu': 'Kid',
|
||||||
|
'SilverWolf': 'Girl',
|
||||||
|
'Qingque': 'Girl',
|
||||||
|
'Pela': 'Girl',
|
||||||
|
'Clara': 'Girl',
|
||||||
|
'Herta': 'Girl',
|
||||||
|
'FuXuan': 'Girl',
|
||||||
|
'Yanqing': 'Boy',
|
||||||
|
'Arlan': 'Boy',
|
||||||
|
'Tingyun': 'Maid',
|
||||||
|
'Sushang': 'Maid',
|
||||||
|
'Seele': 'Maid',
|
||||||
|
'March7th': 'Maid',
|
||||||
|
'Jingliu': 'Maid',
|
||||||
|
'Bronya': 'Maid',
|
||||||
|
'Asta': 'Maid',
|
||||||
|
'Yukong': 'Lady',
|
||||||
|
'Serval': 'Lady',
|
||||||
|
'Natasha': 'Lady',
|
||||||
|
'Kafka': 'Lady',
|
||||||
|
'Himeko': 'Lady',
|
||||||
|
'DanHeng': 'Lad',
|
||||||
|
'Welt': 'Male',
|
||||||
|
'Sampo': 'Male',
|
||||||
|
'Blade': 'Male',
|
||||||
|
'Luocha': 'Male',
|
||||||
|
'JingYuan': 'Male',
|
||||||
|
'Gepard': 'Male',
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import signal
|
from scipy import signal
|
||||||
@ -17,6 +19,8 @@ class OcrCharacterName(OcrWhiteLetterOnComplexBackground):
|
|||||||
|
|
||||||
def after_process(self, result):
|
def after_process(self, result):
|
||||||
result = result.replace('蛆', '妲')
|
result = result.replace('蛆', '妲')
|
||||||
|
# Dan Heng o.ImbibitorLunae
|
||||||
|
result = re.sub(r'[0Oo\-. ]{1,3}Imbi', 'Imbi', result)
|
||||||
|
|
||||||
return super().after_process(result)
|
return super().after_process(result)
|
||||||
|
|
||||||
@ -140,7 +144,7 @@ class CharacterSwitch(UI):
|
|||||||
return selected
|
return selected
|
||||||
|
|
||||||
def _convert_selected_to_character(self, selected: list[int]) -> CharacterList | None:
|
def _convert_selected_to_character(self, selected: list[int]) -> CharacterList | None:
|
||||||
expected_peaks = np.array([201, 279, 357, 435])
|
expected_peaks = [201, 279, 357, 435]
|
||||||
if not selected:
|
if not selected:
|
||||||
logger.warning(f'No current character')
|
logger.warning(f'No current character')
|
||||||
logger.attr('CurrentCharacter', None)
|
logger.attr('CurrentCharacter', None)
|
||||||
@ -227,6 +231,14 @@ class CharacterSwitch(UI):
|
|||||||
if ranged_character in self.characters:
|
if ranged_character in self.characters:
|
||||||
logger.info(f'Use ranged character: {ranged_character}, range={level}')
|
logger.info(f'Use ranged character: {ranged_character}, range={level}')
|
||||||
return ranged_character
|
return ranged_character
|
||||||
|
# No kids, as low camera height may miss enemy aim icon
|
||||||
|
if self.character_current.height == 'Kid':
|
||||||
|
# Switch to whoever tall
|
||||||
|
for height in ['Male', 'Lad', 'Lady', 'Miss', 'Maid', 'Boy', 'Girl']:
|
||||||
|
for tall_character in self.characters:
|
||||||
|
if tall_character.height == height:
|
||||||
|
logger.info(f'No kids, use tall character: {tall_character}')
|
||||||
|
return tall_character
|
||||||
# No ranged characters
|
# No ranged characters
|
||||||
logger.info('No ranged characters in team')
|
logger.info('No ranged characters in team')
|
||||||
return False
|
return False
|
||||||
|
@ -155,7 +155,7 @@ class RoguePathHandler(RogueUI):
|
|||||||
or page_main if previous rogue run had bonus selected but didn't finish any domain
|
or page_main if previous rogue run had bonus selected but didn't finish any domain
|
||||||
"""
|
"""
|
||||||
logger.hr('Rogue path select', level=2)
|
logger.hr('Rogue path select', level=2)
|
||||||
path: RoguePath = RoguePath.find_path(path)
|
path: RoguePath = RoguePath.find_name(path)
|
||||||
logger.info(f'Select path: {path}')
|
logger.info(f'Select path: {path}')
|
||||||
entry = self._get_path_click(path)
|
entry = self._get_path_click(path)
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -36,16 +36,6 @@ class RoguePath(Keyword):
|
|||||||
return [self.__getattribute__(f"{server}_parsed").replace("the", '')
|
return [self.__getattribute__(f"{server}_parsed").replace("the", '')
|
||||||
for server in UI_LANGUAGES if hasattr(self, f"{server}_parsed")]
|
for server in UI_LANGUAGES if hasattr(self, f"{server}_parsed")]
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def find_path(cls, name):
|
|
||||||
if isinstance(name, RoguePath):
|
|
||||||
return name
|
|
||||||
for instance in cls.instances.values():
|
|
||||||
if name == instance.name:
|
|
||||||
return instance
|
|
||||||
# Not found
|
|
||||||
raise ScriptError(f'Cannot find a {cls.__name__} instance that matches "{name}"')
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(repr=False)
|
@dataclass(repr=False)
|
||||||
class RogueResonance(Keyword):
|
class RogueResonance(Keyword):
|
||||||
|
Loading…
Reference in New Issue
Block a user