Merge branch 'dev' into character

This commit is contained in:
Zero 2023-12-27 22:24:37 +08:00 committed by GitHub
commit 32acdec15a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 194 additions and 69 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -610,9 +610,10 @@ class KeywordExtract:
yield hash_ yield hash_
def generate(self): def generate(self):
self.load_keywords(['模拟宇宙', '拟造花萼(金)', '拟造花萼(赤)', '凝滞虚影', '侵蚀隧洞', '历战余响', '忘却之庭']) self.load_keywords(['模拟宇宙', '拟造花萼(金)', '拟造花萼(赤)', '凝滞虚影', '侵蚀隧洞', '历战余响',
'忘却之庭', '虚构叙事'])
self.write_keywords(keyword_class='DungeonNav', output_file='./tasks/dungeon/keywords/nav.py') self.write_keywords(keyword_class='DungeonNav', output_file='./tasks/dungeon/keywords/nav.py')
self.load_keywords(['行动摘要', '生存索引', '每日实训']) self.load_keywords(['行动摘要', '生存索引', '每日实训', '逐光捡金', '战术训练'])
self.write_keywords(keyword_class='DungeonTab', output_file='./tasks/dungeon/keywords/tab.py') self.write_keywords(keyword_class='DungeonTab', output_file='./tasks/dungeon/keywords/tab.py')
self.load_keywords(['前往', '领取', '进行中', '已领取', '本日活跃度已满']) self.load_keywords(['前往', '领取', '进行中', '已领取', '本日活跃度已满'])
self.write_keywords(keyword_class='DailyQuestState', output_file='./tasks/daily/keywords/daily_quest_state.py') self.write_keywords(keyword_class='DailyQuestState', output_file='./tasks/daily/keywords/daily_quest_state.py')

View File

@ -77,10 +77,10 @@ FORGOTTEN_HALL_CHECK = ButtonWrapper(
name='FORGOTTEN_HALL_CHECK', name='FORGOTTEN_HALL_CHECK',
share=Button( share=Button(
file='./assets/share/base/page/FORGOTTEN_HALL_CHECK.png', file='./assets/share/base/page/FORGOTTEN_HALL_CHECK.png',
area=(44, 27, 71, 47), area=(41, 21, 73, 53),
search=(24, 7, 91, 67), search=(21, 1, 93, 73),
color=(91, 87, 90), color=(150, 136, 108),
button=(44, 27, 71, 47), button=(41, 21, 73, 53),
), ),
) )
GACHA_CHECK = ButtonWrapper( GACHA_CHECK = ButtonWrapper(

View File

@ -113,3 +113,33 @@ SURVIVAL_INDEX_LOADED = ButtonWrapper(
button=(451, 286, 476, 302), button=(451, 286, 476, 302),
), ),
) )
TREASURES_LIGHTWARD_CHECK = ButtonWrapper(
name='TREASURES_LIGHTWARD_CHECK',
share=Button(
file='./assets/share/dungeon/ui/TREASURES_LIGHTWARD_CHECK.png',
area=(437, 96, 459, 132),
search=(417, 76, 479, 152),
color=(120, 120, 120),
button=(437, 96, 459, 132),
),
)
TREASURES_LIGHTWARD_CLICK = ButtonWrapper(
name='TREASURES_LIGHTWARD_CLICK',
share=Button(
file='./assets/share/dungeon/ui/TREASURES_LIGHTWARD_CLICK.png',
area=(438, 96, 459, 132),
search=(418, 76, 479, 152),
color=(108, 106, 106),
button=(438, 96, 459, 132),
),
)
TREASURES_LIGHTWARD_LOADED = ButtonWrapper(
name='TREASURES_LIGHTWARD_LOADED',
share=Button(
file='./assets/share/dungeon/ui/TREASURES_LIGHTWARD_LOADED.png',
area=(1029, 288, 1047, 306),
search=(1024, 283, 1052, 311),
color=(149, 149, 152),
button=(1029, 288, 1047, 306),
),
)

View File

@ -60,6 +60,15 @@ class DungeonList(Keyword):
return True return True
return False return False
@cached_property
def is_Pure_Fiction(self):
for word in [
'Pure_Fiction',
]:
if word in self.name:
return True
return False
@cached_property @cached_property
def is_daily_dungeon(self): def is_daily_dungeon(self):
return self.is_Calyx_Golden or self.is_Calyx_Crimson or self.is_Stagnant_Shadow or self.is_Cavern_of_Corrosion return self.is_Calyx_Golden or self.is_Calyx_Crimson or self.is_Stagnant_Shadow or self.is_Cavern_of_Corrosion
@ -85,6 +94,8 @@ class DungeonList(Keyword):
return KEYWORDS_DUNGEON_NAV.Echo_of_War return KEYWORDS_DUNGEON_NAV.Echo_of_War
if self.is_Forgotten_Hall: if self.is_Forgotten_Hall:
return KEYWORDS_DUNGEON_NAV.Forgotten_Hall return KEYWORDS_DUNGEON_NAV.Forgotten_Hall
if self.is_Pure_Fiction:
return KEYWORDS_DUNGEON_NAV.Pure_Fiction
raise ScriptError(f'Cannot convert {self} to DungeonNav, please check keyword extractions') raise ScriptError(f'Cannot convert {self} to DungeonNav, please check keyword extractions')

View File

@ -66,3 +66,12 @@ Forgotten_Hall = DungeonNav(
jp='忘却の庭', jp='忘却の庭',
es='Salón olvidado', es='Salón olvidado',
) )
Pure_Fiction = DungeonNav(
id=8,
name='Pure_Fiction',
cn='虚构叙事',
cht='虛構敘事',
en='Pure Fiction',
jp='虚構叙事',
es='Pura ficción',
)

View File

@ -30,3 +30,21 @@ Daily_Training = DungeonTab(
jp='デイリー訓練', jp='デイリー訓練',
es='Entrenamiento diario', es='Entrenamiento diario',
) )
Treasures_Lightward = DungeonTab(
id=4,
name='Treasures_Lightward',
cn='逐光捡金',
cht='逐光撿金',
en='Treasures Lightward',
jp='光を追い、黄金を掴む',
es='En busca de fortuna',
)
Strategic_Training = DungeonTab(
id=5,
name='Strategic_Training',
cn='战术训练',
cht='戰術訓練',
en='Strategic Training',
jp='戦術訓練',
es='Entrenamiento estratégico',
)

View File

@ -57,6 +57,11 @@ SWITCH_DUNGEON_TAB.add_state(
check_button=SURVIVAL_INDEX_CHECK, check_button=SURVIVAL_INDEX_CHECK,
click_button=SURVIVAL_INDEX_CLICK click_button=SURVIVAL_INDEX_CLICK
) )
SWITCH_DUNGEON_TAB.add_state(
KEYWORDS_DUNGEON_TAB.Treasures_Lightward,
check_button=TREASURES_LIGHTWARD_CHECK,
click_button=TREASURES_LIGHTWARD_CLICK
)
class OcrDungeonNav(Ocr): class OcrDungeonNav(Ocr):
@ -145,7 +150,10 @@ class DungeonUI(DungeonState):
self._dungeon_wait_daily_training_loaded() self._dungeon_wait_daily_training_loaded()
elif state == KEYWORDS_DUNGEON_TAB.Survival_Index: elif state == KEYWORDS_DUNGEON_TAB.Survival_Index:
logger.info(f'Tab goto {state}, wait until loaded') logger.info(f'Tab goto {state}, wait until loaded')
self._dungeon_wait_survival_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 return True
else: else:
return False return False
@ -173,7 +181,7 @@ class DungeonUI(DungeonState):
logger.info('Daily training loaded') logger.info('Daily training loaded')
return True return True
def _dungeon_wait_survival_loaded(self, skip_first_screenshot=True): def _dungeon_wait_survival_index_loaded(self, skip_first_screenshot=True):
""" """
Returns: Returns:
bool: True if wait success, False if wait timeout. bool: True if wait success, False if wait timeout.
@ -195,6 +203,28 @@ class DungeonUI(DungeonState):
logger.info('Survival index loaded') logger.info('Survival index loaded')
return True return True
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()
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')
return True
def _dungeon_wait_until_echo_or_war_stabled(self, skip_first_screenshot=True): def _dungeon_wait_until_echo_or_war_stabled(self, skip_first_screenshot=True):
""" """
Returns: Returns:
@ -273,6 +303,10 @@ class DungeonUI(DungeonState):
# Update points if possible # Update points if possible
if DUNGEON_NAV_LIST.is_row_selected(button, main=self): if DUNGEON_NAV_LIST.is_row_selected(button, main=self):
self.dungeon_update_simuni() 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: else:
# To start from any list states. # To start from any list states.
logger.info('DUNGEON_NAV_LIST not at top') logger.info('DUNGEON_NAV_LIST not at top')
@ -286,6 +320,8 @@ class DungeonUI(DungeonState):
KEYWORDS_DUNGEON_NAV.Calyx_Crimson, KEYWORDS_DUNGEON_NAV.Calyx_Crimson,
KEYWORDS_DUNGEON_NAV.Stagnant_Shadow, KEYWORDS_DUNGEON_NAV.Stagnant_Shadow,
KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion, KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion,
KEYWORDS_DUNGEON_NAV.Forgotten_Hall,
KEYWORDS_DUNGEON_NAV.Pure_Fiction,
]: ]:
button = DUNGEON_NAV_LIST.keyword2button(dungeon.dungeon_nav) button = DUNGEON_NAV_LIST.keyword2button(dungeon.dungeon_nav)
if button: if button:

View File

@ -7,39 +7,39 @@ CHARACTER_1 = ButtonWrapper(
name='CHARACTER_1', name='CHARACTER_1',
share=Button( share=Button(
file='./assets/share/forgotten_hall/team/CHARACTER_1.png', file='./assets/share/forgotten_hall/team/CHARACTER_1.png',
area=(44, 172, 140, 196), area=(32, 190, 128, 214),
search=(24, 152, 160, 216), search=(12, 170, 148, 234),
color=(211, 210, 213), color=(212, 212, 210),
button=(44, 106, 140, 217), button=(32, 124, 128, 236),
), ),
) )
CHARACTER_2 = ButtonWrapper( CHARACTER_2 = ButtonWrapper(
name='CHARACTER_2', name='CHARACTER_2',
share=Button( share=Button(
file='./assets/share/forgotten_hall/team/CHARACTER_2.png', file='./assets/share/forgotten_hall/team/CHARACTER_2.png',
area=(150, 172, 246, 196), area=(144, 190, 240, 214),
search=(130, 152, 266, 216), search=(124, 170, 260, 234),
color=(212, 211, 210), color=(216, 213, 214),
button=(150, 106, 246, 218), button=(144, 124, 240, 236),
), ),
) )
CHARACTER_3 = ButtonWrapper( CHARACTER_3 = ButtonWrapper(
name='CHARACTER_3', name='CHARACTER_3',
share=Button( share=Button(
file='./assets/share/forgotten_hall/team/CHARACTER_3.png', file='./assets/share/forgotten_hall/team/CHARACTER_3.png',
area=(256, 172, 352, 196), area=(256, 190, 352, 214),
search=(236, 152, 372, 216), search=(236, 170, 372, 234),
color=(214, 211, 212), color=(212, 211, 214),
button=(256, 106, 352, 218), button=(256, 124, 352, 236),
), ),
) )
CHARACTER_4 = ButtonWrapper( CHARACTER_4 = ButtonWrapper(
name='CHARACTER_4', name='CHARACTER_4',
share=Button( share=Button(
file='./assets/share/forgotten_hall/team/CHARACTER_4.png', file='./assets/share/forgotten_hall/team/CHARACTER_4.png',
area=(44, 304, 140, 328), area=(32, 322, 128, 346),
search=(24, 284, 160, 348), search=(12, 302, 148, 366),
color=(212, 211, 213), color=(213, 212, 211),
button=(44, 238, 140, 350), button=(32, 256, 128, 368),
), ),
) )

View File

@ -17,51 +17,69 @@ EFFECT_NOTIFICATION = ButtonWrapper(
name='EFFECT_NOTIFICATION', name='EFFECT_NOTIFICATION',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/EFFECT_NOTIFICATION.png', file='./assets/share/forgotten_hall/ui/EFFECT_NOTIFICATION.png',
area=(237, 302, 315, 380), area=(250, 330, 320, 388),
search=(217, 282, 335, 400), search=(230, 310, 340, 408),
color=(128, 114, 85), color=(166, 147, 108),
button=(237, 302, 315, 380), button=(250, 330, 320, 388),
), ),
) )
ENTER_FORGOTTEN_HALL_DUNGEON = ButtonWrapper( ENTER_FORGOTTEN_HALL_DUNGEON = ButtonWrapper(
name='ENTER_FORGOTTEN_HALL_DUNGEON', name='ENTER_FORGOTTEN_HALL_DUNGEON',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/ENTER_FORGOTTEN_HALL_DUNGEON.png', file='./assets/share/forgotten_hall/ui/ENTER_FORGOTTEN_HALL_DUNGEON.png',
area=(989, 649, 1231, 684), area=(953, 640, 1225, 676),
search=(969, 629, 1251, 704), search=(933, 620, 1245, 696),
color=(214, 214, 217), color=(217, 217, 219),
button=(989, 649, 1231, 684), button=(953, 640, 1225, 676),
), ),
) )
ENTRANCE_CHECKED = ButtonWrapper( ENTRANCE_CHECKED = ButtonWrapper(
name='ENTRANCE_CHECKED', name='ENTRANCE_CHECKED',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/ENTRANCE_CHECKED.png', file='./assets/share/forgotten_hall/ui/ENTRANCE_CHECKED.png',
area=(55, 632, 71, 650), area=(44, 655, 60, 673),
search=(35, 612, 91, 670), search=(24, 635, 80, 693),
color=(156, 156, 157), color=(156, 156, 158),
button=(55, 632, 71, 650), button=(44, 655, 60, 673),
), ),
) )
LAST_VASTIGES_CHECK = ButtonWrapper( LAST_VASTIGES_CHECK = ButtonWrapper(
name='LAST_VASTIGES_CHECK', name='LAST_VASTIGES_CHECK',
share=Button( share=[
file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.png', Button(
area=(25, 190, 96, 262), file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.png',
search=(11, 73, 111, 461), area=(25, 190, 96, 262),
color=(94, 126, 162), search=(11, 73, 111, 461),
button=(25, 190, 96, 262), color=(94, 126, 162),
), button=(25, 190, 96, 262),
),
Button(
file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CHECK.2.png',
area=(46, 274, 98, 348),
search=(11, 73, 111, 461),
color=(38, 53, 71),
button=(46, 274, 98, 348),
),
],
) )
LAST_VASTIGES_CLICK = ButtonWrapper( LAST_VASTIGES_CLICK = ButtonWrapper(
name='LAST_VASTIGES_CLICK', name='LAST_VASTIGES_CLICK',
share=Button( share=[
file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.png', Button(
area=(32, 196, 90, 254), file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.png',
search=(11, 73, 111, 461), area=(32, 196, 90, 254),
color=(49, 64, 87), search=(11, 73, 111, 461),
button=(32, 196, 90, 254), color=(49, 64, 87),
), button=(32, 196, 90, 254),
),
Button(
file='./assets/share/forgotten_hall/ui/LAST_VASTIGES_CLICK.2.png',
area=(51, 281, 90, 341),
search=(11, 73, 111, 461),
color=(22, 29, 39),
button=(51, 281, 90, 341),
),
],
) )
MEMORY_OF_CHAOS_CHECK = ButtonWrapper( MEMORY_OF_CHAOS_CHECK = ButtonWrapper(
name='MEMORY_OF_CHAOS_CHECK', name='MEMORY_OF_CHAOS_CHECK',
@ -97,40 +115,40 @@ SEAT_1 = ButtonWrapper(
name='SEAT_1', name='SEAT_1',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/SEAT_1.png', file='./assets/share/forgotten_hall/ui/SEAT_1.png',
area=(946, 518, 953, 533), area=(957, 549, 966, 574),
search=(926, 498, 973, 553), search=(937, 529, 986, 594),
color=(66, 68, 89), color=(77, 78, 87),
button=(946, 518, 953, 533), button=(957, 549, 966, 574),
), ),
) )
SEAT_2 = ButtonWrapper( SEAT_2 = ButtonWrapper(
name='SEAT_2', name='SEAT_2',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/SEAT_2.png', file='./assets/share/forgotten_hall/ui/SEAT_2.png',
area=(1026, 518, 1033, 533), area=(1034, 549, 1043, 574),
search=(1006, 498, 1053, 553), search=(1014, 529, 1063, 594),
color=(68, 70, 92), color=(77, 77, 86),
button=(1026, 518, 1033, 533), button=(1034, 549, 1043, 574),
), ),
) )
SEAT_3 = ButtonWrapper( SEAT_3 = ButtonWrapper(
name='SEAT_3', name='SEAT_3',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/SEAT_3.png', file='./assets/share/forgotten_hall/ui/SEAT_3.png',
area=(1106, 518, 1113, 532), area=(1111, 549, 1120, 574),
search=(1086, 498, 1133, 552), search=(1091, 529, 1140, 594),
color=(67, 69, 87), color=(76, 77, 85),
button=(1106, 518, 1113, 532), button=(1111, 549, 1120, 574),
), ),
) )
SEAT_4 = ButtonWrapper( SEAT_4 = ButtonWrapper(
name='SEAT_4', name='SEAT_4',
share=Button( share=Button(
file='./assets/share/forgotten_hall/ui/SEAT_4.png', file='./assets/share/forgotten_hall/ui/SEAT_4.png',
area=(1186, 518, 1193, 532), area=(1188, 549, 1197, 574),
search=(1166, 498, 1213, 552), search=(1168, 529, 1217, 594),
color=(67, 69, 86), color=(76, 77, 85),
button=(1186, 518, 1193, 532), button=(1188, 549, 1197, 574),
), ),
) )
TELEPORT = ButtonWrapper( TELEPORT = ButtonWrapper(

View File

@ -97,10 +97,11 @@ class DraggableStageList(DraggableList):
return main.appear(ENTRANCE_CHECKED) return main.appear(ENTRANCE_CHECKED)
def load_rows(self, main: ModuleBase): def load_rows(self, main: ModuleBase):
if not main.appear(FORGOTTEN_HALL_CHECK): if main.appear(MEMORY_OF_CHAOS_CHECK) or main.appear(LAST_VASTIGES_CHECK):
return super().load_rows(main=main)
else:
logger.info('Not in forgotten hall, skip load_rows()') logger.info('Not in forgotten hall, skip load_rows()')
return return
return super().load_rows(main=main)
STAGE_LIST = DraggableStageList("ForgottenHallStageList", keyword_class=ForgottenHallStage, STAGE_LIST = DraggableStageList("ForgottenHallStageList", keyword_class=ForgottenHallStage,
@ -184,10 +185,11 @@ class ForgottenHallUI(DungeonUI, ForgottenHallTeam):
if self.appear(FORGOTTEN_HALL_CHECK): if self.appear(FORGOTTEN_HALL_CHECK):
logger.info('Already in forgotten hall') logger.info('Already in forgotten hall')
else: else:
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Treasures_Lightward)
self._dungeon_nav_goto(dungeon) self._dungeon_nav_goto(dungeon)
self.stage_choose(dungeon) self.stage_choose(dungeon)
logger.info(f'Stage list select: {stage_keyword}')
STAGE_LIST.select_row(stage_keyword, main=self) STAGE_LIST.select_row(stage_keyword, main=self)
def exit_dungeon(self, skip_first_screenshot=True): def exit_dungeon(self, skip_first_screenshot=True):