Merge branch 'master' into dev

This commit is contained in:
LmeSzinc 2024-05-20 00:20:03 +08:00
commit aacf1650fc
20 changed files with 174 additions and 80 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -126,6 +126,7 @@ class GenerateAssignmentEventGroup(GenerateKeyword):
def iter_keywords(self) -> Iterable[dict]: def iter_keywords(self) -> Iterable[dict]:
yield dict(text_id=self.find_keyword('空间站特派', lang='cn')[0]) yield dict(text_id=self.find_keyword('空间站特派', lang='cn')[0])
yield dict(text_id=self.find_keyword('关于波提欧的一切…', lang='cn')[0])
class GenerateAssignmentEventEntry(GenerateKeyword): class GenerateAssignmentEventEntry(GenerateKeyword):

View File

@ -1113,7 +1113,7 @@
"20": "20 Hours" "20": "20 Hours"
}, },
"Event": { "Event": {
"name": "Complete Event Assignments First", "name": "Complete Event Assignments",
"help": "" "help": ""
}, },
"Assignment": { "Assignment": {

View File

@ -1113,7 +1113,7 @@
"20": "20小时" "20": "20小时"
}, },
"Event": { "Event": {
"name": "有活动时优先做活动委托", "name": "有活动时参加活动委托",
"help": "" "help": ""
}, },
"Assignment": { "Assignment": {

View File

@ -1113,7 +1113,7 @@
"20": "20小時" "20": "20小時"
}, },
"Event": { "Event": {
"name": "有活動時優先做活動委託", "name": "有活動時參加活動委託",
"help": "" "help": ""
}, },
"Assignment": { "Assignment": {

View File

@ -1,12 +1,11 @@
from tasks.assignment.assets.assets_assignment_ui import ( from tasks.assignment.assets.assets_assignment_ui import (
ALL_ABOUT_BOOTHILL_CHECK, ALL_ABOUT_BOOTHILL_CLICK,
CHARACTER_MATERIALS_CHECK, CHARACTER_MATERIALS_CLICK, CHARACTER_MATERIALS_CHECK, CHARACTER_MATERIALS_CLICK,
EXP_MATERIALS_CREDITS_CHECK, EXP_MATERIALS_CREDITS_CLICK, GROUP_SEARCH, EXP_MATERIALS_CREDITS_CHECK, EXP_MATERIALS_CREDITS_CLICK, GROUP_SEARCH,
SPACE_STATION_TASK_FORCE_CHECK, SPACE_STATION_TASK_FORCE_CLICK, SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK)
SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK
)
for group_button_wrapper in ( for group_button_wrapper in (
SPACE_STATION_TASK_FORCE_CHECK, SPACE_STATION_TASK_FORCE_CLICK, ALL_ABOUT_BOOTHILL_CHECK, ALL_ABOUT_BOOTHILL_CLICK,
CHARACTER_MATERIALS_CHECK, CHARACTER_MATERIALS_CLICK, CHARACTER_MATERIALS_CHECK, CHARACTER_MATERIALS_CLICK,
EXP_MATERIALS_CREDITS_CHECK, EXP_MATERIALS_CREDITS_CLICK, EXP_MATERIALS_CREDITS_CHECK, EXP_MATERIALS_CREDITS_CLICK,
SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK, SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK,

View File

@ -5,30 +5,57 @@ from module.base.button import Button, ButtonWrapper
ASSIGNMENT_START = ButtonWrapper( ASSIGNMENT_START = ButtonWrapper(
name='ASSIGNMENT_START', name='ASSIGNMENT_START',
cn=Button( cn=[
Button(
file='./assets/cn/assignment/dispatch/ASSIGNMENT_START.png', file='./assets/cn/assignment/dispatch/ASSIGNMENT_START.png',
area=(563, 341, 716, 376), area=(563, 341, 716, 376),
search=(552, 299, 725, 412), search=(552, 299, 725, 412),
color=(103, 92, 72), color=(103, 92, 72),
button=(563, 341, 716, 376), button=(563, 341, 716, 376),
), ),
en=Button( Button(
file='./assets/cn/assignment/dispatch/ASSIGNMENT_START.2.png',
area=(579, 373, 702, 405),
search=(552, 299, 725, 412),
color=(84, 75, 59),
button=(579, 373, 702, 405),
),
],
en=[
Button(
file='./assets/en/assignment/dispatch/ASSIGNMENT_START.png', file='./assets/en/assignment/dispatch/ASSIGNMENT_START.png',
area=(693, 343, 831, 374), area=(693, 343, 831, 374),
search=(669, 297, 831, 416), search=(669, 297, 831, 416),
color=(95, 86, 67), color=(95, 86, 67),
button=(693, 343, 831, 374), button=(693, 343, 831, 374),
), ),
Button(
file='./assets/en/assignment/dispatch/ASSIGNMENT_START.2.png',
area=(676, 376, 787, 404),
search=(669, 297, 831, 416),
color=(80, 71, 56),
button=(676, 376, 787, 404),
),
],
) )
ASSIGNMENT_STARTED_CHECK = ButtonWrapper( ASSIGNMENT_STARTED_CHECK = ButtonWrapper(
name='ASSIGNMENT_STARTED_CHECK', name='ASSIGNMENT_STARTED_CHECK',
share=Button( share=[
Button(
file='./assets/share/assignment/dispatch/ASSIGNMENT_STARTED_CHECK.png', file='./assets/share/assignment/dispatch/ASSIGNMENT_STARTED_CHECK.png',
area=(542, 412, 1156, 422), area=(542, 412, 1156, 422),
search=(522, 392, 1176, 442), search=(522, 392, 1176, 442),
color=(232, 230, 226), color=(232, 230, 226),
button=(542, 412, 1156, 422), button=(542, 412, 1156, 422),
), ),
Button(
file='./assets/share/assignment/dispatch/ASSIGNMENT_STARTED_CHECK.2.png',
area=(542, 412, 1156, 422),
search=(522, 392, 1176, 442),
color=(254, 244, 221),
button=(542, 412, 1156, 422),
),
],
) )
CHARACTER_1 = ButtonWrapper( CHARACTER_1 = ButtonWrapper(
name='CHARACTER_1', name='CHARACTER_1',

View File

@ -3,6 +3,40 @@ from module.base.button import Button, ButtonWrapper
# This file was auto-generated, do not modify it manually. To generate: # This file was auto-generated, do not modify it manually. To generate:
# ``` python -m dev_tools.button_extract ``` # ``` python -m dev_tools.button_extract ```
ALL_ABOUT_BOOTHILL_CHECK = ButtonWrapper(
name='ALL_ABOUT_BOOTHILL_CHECK',
cn=Button(
file='./assets/cn/assignment/ui/ALL_ABOUT_BOOTHILL_CHECK.png',
area=(153, 98, 226, 118),
search=(133, 78, 246, 138),
color=(186, 180, 164),
button=(153, 98, 226, 118),
),
en=Button(
file='./assets/en/assignment/ui/ALL_ABOUT_BOOTHILL_CHECK.png',
area=(154, 89, 240, 129),
search=(134, 69, 260, 149),
color=(207, 201, 183),
button=(154, 89, 240, 129),
),
)
ALL_ABOUT_BOOTHILL_CLICK = ButtonWrapper(
name='ALL_ABOUT_BOOTHILL_CLICK',
cn=Button(
file='./assets/cn/assignment/ui/ALL_ABOUT_BOOTHILL_CLICK.png',
area=(153, 98, 227, 119),
search=(133, 78, 247, 139),
color=(80, 79, 77),
button=(153, 98, 227, 119),
),
en=Button(
file='./assets/en/assignment/ui/ALL_ABOUT_BOOTHILL_CLICK.png',
area=(154, 90, 241, 128),
search=(134, 70, 261, 148),
color=(59, 57, 56),
button=(154, 90, 241, 128),
),
)
CHARACTER_MATERIALS_CHECK = ButtonWrapper( CHARACTER_MATERIALS_CHECK = ButtonWrapper(
name='CHARACTER_MATERIALS_CHECK', name='CHARACTER_MATERIALS_CHECK',
cn=Button( cn=Button(

View File

@ -2,7 +2,9 @@ from datetime import datetime
from module.logger import logger from module.logger import logger
from tasks.assignment.claim import AssignmentClaim from tasks.assignment.claim import AssignmentClaim
from tasks.assignment.keywords import (AssignmentEntry, AssignmentEventGroup, KEYWORDS_ASSIGNMENT_GROUP) from tasks.assignment.keywords import (KEYWORDS_ASSIGNMENT_GROUP,
AssignmentEntry, AssignmentEventEntry,
AssignmentEventGroup)
from tasks.assignment.ui import AssignmentStatus from tasks.assignment.ui import AssignmentStatus
from tasks.base.page import page_assignment, page_menu from tasks.base.page import page_assignment, page_menu
from tasks.daily.keywords import KEYWORDS_DAILY_QUEST from tasks.daily.keywords import KEYWORDS_DAILY_QUEST
@ -10,7 +12,7 @@ from tasks.daily.synthesize import SynthesizeUI
class Assignment(AssignmentClaim, SynthesizeUI): class Assignment(AssignmentClaim, SynthesizeUI):
def run(self, assignments: list[AssignmentEntry] = None, duration: int = None, event_first: bool = None): def run(self, assignments: list[AssignmentEntry] = None, duration: int = None, join_event: bool = None):
self.config.update_battle_pass_quests() self.config.update_battle_pass_quests()
self.config.update_daily_quests() self.config.update_daily_quests()
@ -26,22 +28,21 @@ class Assignment(AssignmentClaim, SynthesizeUI):
'There are duplicate assignments in config, check it out') 'There are duplicate assignments in config, check it out')
if duration is None: if duration is None:
duration = self.config.Assignment_Duration duration = self.config.Assignment_Duration
if event_first is None: if join_event is None:
event_first = self.config.Assignment_Event join_event = self.config.Assignment_Event
self.dispatched = dict() self.dispatched = dict()
self.has_new_dispatch = False self.has_new_dispatch = False
self.ensure_scroll_top(page_menu) self.ensure_scroll_top(page_menu)
self.ui_ensure(page_assignment) self.ui_ensure(page_assignment)
self._wait_until_group_loaded()
event_ongoing = next(( event_ongoing = next((
g for g in self._iter_groups() g for g in self._iter_groups()
if isinstance(g, AssignmentEventGroup) if isinstance(g, AssignmentEventGroup)
), None) ), None)
if event_first and event_ongoing is not None: if join_event and event_ongoing is not None:
undispatched = assignments if self._check_event():
remain = self._check_all() self._check_event()
remain = self._dispatch_event(remain)
else:
# Iterate in user-specified order, return undispatched ones # Iterate in user-specified order, return undispatched ones
undispatched = list(self._check_inlist(assignments, duration)) undispatched = list(self._check_inlist(assignments, duration))
remain = self._check_all() remain = self._check_all()
@ -89,13 +90,15 @@ class Assignment(AssignmentClaim, SynthesizeUI):
logger.hr('Assignment check inlist', level=1) logger.hr('Assignment check inlist', level=1)
logger.info( logger.info(
f'User specified assignments: {", ".join([x.name for x in assignments])}') f'User specified assignments: {", ".join([x.name for x in assignments])}')
_, remain, _ = self._limit_status remain = None
for assignment in assignments: for assignment in assignments:
if assignment in self.dispatched: if assignment in self.dispatched:
continue continue
logger.hr('Assignment inlist', level=2) logger.hr('Assignment inlist', level=2)
logger.info(f'Check assignment inlist: {assignment}') logger.info(f'Check assignment inlist: {assignment}')
self.goto_entry(assignment) self.goto_entry(assignment)
if remain is None:
_, remain, _ = self._limit_status
status = self._check_assignment_status() status = self._check_assignment_status()
if status == AssignmentStatus.CLAIMABLE: if status == AssignmentStatus.CLAIMABLE:
self.claim(assignment, duration, should_redispatch=True) self.claim(assignment, duration, should_redispatch=True)
@ -121,10 +124,16 @@ class Assignment(AssignmentClaim, SynthesizeUI):
""" """
logger.hr('Assignment check all', level=1) logger.hr('Assignment check all', level=1)
current, remain, _ = self._limit_status current, remain, _ = self._limit_status
len_dispatched = len([
x for x in self.dispatched.keys()
if not isinstance(x, AssignmentEventEntry)
])
# current = #Claimable + #Dispatched # current = #Claimable + #Dispatched
if current == len(self.dispatched): if current == len_dispatched:
return remain return remain
for group in self._iter_groups(): for group in self._iter_groups():
if isinstance(group, AssignmentEventGroup):
continue
self.goto_group(group) self.goto_group(group)
insight = False insight = False
for assignment in self._iter_entries(): for assignment in self._iter_entries():
@ -139,14 +148,15 @@ class Assignment(AssignmentClaim, SynthesizeUI):
current -= 1 current -= 1
remain += 1 remain += 1
insight = True # Order of entries change after claiming insight = True # Order of entries change after claiming
if current == len(self.dispatched): if current == len_dispatched:
return remain return remain
continue continue
if status == AssignmentStatus.DISPATCHED: if status == AssignmentStatus.DISPATCHED:
self.dispatched[assignment] = datetime.now() + \ self.dispatched[assignment] = datetime.now() + \
self._get_assignment_time() self._get_assignment_time()
len_dispatched += 1
insight = False # Order of entries does not change here insight = False # Order of entries does not change here
if current == len(self.dispatched): if current == len_dispatched:
return remain return remain
continue continue
break break
@ -183,10 +193,9 @@ class Assignment(AssignmentClaim, SynthesizeUI):
if remain <= 0: if remain <= 0:
return return
def _dispatch_event(self, remain: int): def _check_event(self):
if remain <= 0: logger.hr('Assignment check event', level=1)
return remain claimed = False
logger.hr('Assignment dispatch event', level=1)
for group in self._iter_groups(): for group in self._iter_groups():
if not isinstance(group, AssignmentEventGroup): if not isinstance(group, AssignmentEventGroup):
continue continue
@ -199,12 +208,14 @@ class Assignment(AssignmentClaim, SynthesizeUI):
# Order of entries does not change during iteration # Order of entries does not change during iteration
self.goto_entry(assignment, insight=False) self.goto_entry(assignment, insight=False)
status = self._check_assignment_status() status = self._check_assignment_status()
# Should only be dispatchable or locked after _check_all if status == AssignmentStatus.LOCKED:
continue
if status == AssignmentStatus.CLAIMABLE:
self.claim(assignment, None, should_redispatch=False)
claimed = True
if status == AssignmentStatus.DISPATCHABLE: if status == AssignmentStatus.DISPATCHABLE:
self.dispatch(assignment, None) self.dispatch(assignment, None)
remain -= 1 if status == AssignmentStatus.DISPATCHED:
if remain <= 0: self.dispatched[assignment] = datetime.now() + \
return remain self._get_assignment_time()
continue return claimed
break
return remain

View File

@ -30,7 +30,7 @@ KEYWORDS_ASSIGNMENT_GROUP.Synthesis_Materials.entries = (
KEYWORDS_ASSIGNMENT_ENTRY.Fragments_of_Illusory_Dreams, KEYWORDS_ASSIGNMENT_ENTRY.Fragments_of_Illusory_Dreams,
KEYWORDS_ASSIGNMENT_ENTRY.Scalpel_and_Screwdriver, KEYWORDS_ASSIGNMENT_ENTRY.Scalpel_and_Screwdriver,
) )
KEYWORDS_ASSIGNMENT_EVENT_GROUP.Space_Station_Task_Force.entries = ( KEYWORDS_ASSIGNMENT_EVENT_GROUP.All_About_Boothill.entries = (
KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Activate_Genetic_Samples, KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Activate_Genetic_Samples,
KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Reproduce_Experimental_Data, KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Reproduce_Experimental_Data,
KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Burned_Warehouse, KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Burned_Warehouse,
@ -60,7 +60,7 @@ for group in (
KEYWORDS_ASSIGNMENT_GROUP.Character_Materials, KEYWORDS_ASSIGNMENT_GROUP.Character_Materials,
KEYWORDS_ASSIGNMENT_GROUP.EXP_Materials_Credits, KEYWORDS_ASSIGNMENT_GROUP.EXP_Materials_Credits,
KEYWORDS_ASSIGNMENT_GROUP.Synthesis_Materials, KEYWORDS_ASSIGNMENT_GROUP.Synthesis_Materials,
KEYWORDS_ASSIGNMENT_EVENT_GROUP.Space_Station_Task_Force, KEYWORDS_ASSIGNMENT_EVENT_GROUP.All_About_Boothill,
): ):
for entry in group.entries: for entry in group.entries:
assert entry.group is None assert entry.group is None

View File

@ -12,3 +12,12 @@ Space_Station_Task_Force = AssignmentEventGroup(
jp='ステーション特派', jp='ステーション特派',
es='Comando de la Estación Espacial', es='Comando de la Estación Espacial',
) )
All_About_Boothill = AssignmentEventGroup(
id=2,
name='All_About_Boothill',
cn='关于波提欧的一切…',
cht='關於波提歐的一切……',
en='All About Boothill...',
jp='ブートヒルに関するすべて…',
es='Todo sobre Boothill...',
)

View File

@ -8,13 +8,14 @@ from module.base.timer import Timer
from module.exception import ScriptError from module.exception import ScriptError
from module.logger import logger from module.logger import logger
from module.ocr.ocr import DigitCounter, Duration, Ocr from module.ocr.ocr import DigitCounter, Duration, Ocr
from tasks.dungeon.ui import DungeonTabSwitch as Switch
from module.ui.draggable_list import DraggableList from module.ui.draggable_list import DraggableList
from tasks.assignment.assets.assets_assignment_claim import CLAIM from tasks.assignment.assets.assets_assignment_claim import CLAIM
from tasks.assignment.assets.assets_assignment_dispatch import EMPTY_SLOT from tasks.assignment.assets.assets_assignment_dispatch import EMPTY_SLOT
from tasks.assignment.assets.assets_assignment_ui import * from tasks.assignment.assets.assets_assignment_ui import *
from tasks.assignment.keywords import * from tasks.assignment.keywords import *
from tasks.base.assets.assets_base_page import ASSIGNMENT_CHECK
from tasks.base.ui import UI from tasks.base.ui import UI
from tasks.dungeon.ui import DungeonTabSwitch as Switch
class AssignmentStatus(Enum): class AssignmentStatus(Enum):
@ -31,17 +32,20 @@ class AssignmentOcr(Ocr):
OCR_REPLACE = { OCR_REPLACE = {
'cn': [ 'cn': [
(KEYWORDS_ASSIGNMENT_ENTRY.Winter_Soldiers.name, '[黑]冬的战士们'), (KEYWORDS_ASSIGNMENT_ENTRY.Winter_Soldiers, '[黑]冬的战士们'),
(KEYWORDS_ASSIGNMENT_ENTRY.Born_to_Obey.name, '[牛]而服从'), (KEYWORDS_ASSIGNMENT_ENTRY.Born_to_Obey, '[牛]而服从'),
(KEYWORDS_ASSIGNMENT_ENTRY.Root_Out_the_Turpitude.name, (KEYWORDS_ASSIGNMENT_ENTRY.Root_Out_the_Turpitude,
'根除恶[擎薯尊掌鞋]?'), '根除恶[擎薯尊掌鞋]?'),
(KEYWORDS_ASSIGNMENT_ENTRY.Akashic_Records.name, '阿[未][夏复]记录'), (KEYWORDS_ASSIGNMENT_ENTRY.Akashic_Records, '阿[未][夏复]记录'),
(KEYWORDS_ASSIGNMENT_ENTRY.Legend_of_the_Puppet_Master.name, '^师传说'), (KEYWORDS_ASSIGNMENT_ENTRY.Legend_of_the_Puppet_Master, '^师传说'),
(KEYWORDS_ASSIGNMENT_ENTRY.The_Wages_of_Humanity.name, '[赠]养人类'), (KEYWORDS_ASSIGNMENT_ENTRY.The_Wages_of_Humanity, '[赠]养人类'),
(KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Car_Thief, '.*的偷车贼.*'),
(KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Synesthesia_Beacon_Function_Iteration, '联觉信标功能[送]代'),
], ],
'en': [ 'en': [
# (KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Food_Improvement_Plan.name, # (KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Food_Improvement_Plan.name,
# 'Food\s*[I]{0}mprovement Plan'), # 'Food\s*[I]{0}mprovement Plan'),
(KEYWORDS_ASSIGNMENT_EVENT_ENTRY.Car_Thief, '.*Car Thief.*'),
] ]
} }
@ -50,7 +54,10 @@ class AssignmentOcr(Ocr):
rules = AssignmentOcr.OCR_REPLACE.get(self.lang) rules = AssignmentOcr.OCR_REPLACE.get(self.lang)
if rules is None: if rules is None:
return None return None
return re.compile('|'.join('(?P<%s>%s)' % pair for pair in rules)) return re.compile('|'.join(
f'(?P<{kw.name}>{pat})'
for kw, pat in rules
))
def filter_detected(self, result) -> bool: def filter_detected(self, result) -> bool:
# Drop duration rows # Drop duration rows
@ -78,17 +85,17 @@ class AssignmentOcr(Ocr):
matched = self.ocr_regex.fullmatch(result) matched = self.ocr_regex.fullmatch(result)
if matched is None: if matched is None:
return result return result
keyword_lang = self.lang
for keyword_class in ( for keyword_class in (
KEYWORDS_ASSIGNMENT_ENTRY, KEYWORDS_ASSIGNMENT_ENTRY,
KEYWORDS_ASSIGNMENT_EVENT_ENTRY, KEYWORDS_ASSIGNMENT_EVENT_ENTRY,
): ):
matched = getattr(keyword_class, matched.lastgroup, None) kw = getattr(keyword_class, matched.lastgroup, None)
if matched is not None: if kw is not None:
matched = kw
break break
else: else:
raise ScriptError(f'No keyword found for {matched.lastgroup}') raise ScriptError(f'No keyword found for {matched.lastgroup}')
matched = getattr(matched, keyword_lang) matched = getattr(matched, self.lang)
logger.attr(name=f'{self.name} after_process', logger.attr(name=f'{self.name} after_process',
text=f'{result} -> {matched}') text=f'{result} -> {matched}')
return matched return matched
@ -98,10 +105,15 @@ ASSIGNMENT_GROUP_SWITCH = Switch(
'AssignmentGroupSwitch', 'AssignmentGroupSwitch',
is_selector=True is_selector=True
) )
# ASSIGNMENT_GROUP_SWITCH.add_state(
# KEYWORDS_ASSIGNMENT_EVENT_GROUP.Space_Station_Task_Force,
# check_button=SPACE_STATION_TASK_FORCE_CHECK,
# click_button=SPACE_STATION_TASK_FORCE_CLICK
# )
ASSIGNMENT_GROUP_SWITCH.add_state( ASSIGNMENT_GROUP_SWITCH.add_state(
KEYWORDS_ASSIGNMENT_EVENT_GROUP.Space_Station_Task_Force, KEYWORDS_ASSIGNMENT_EVENT_GROUP.All_About_Boothill,
check_button=SPACE_STATION_TASK_FORCE_CHECK, check_button=ALL_ABOUT_BOOTHILL_CHECK,
click_button=SPACE_STATION_TASK_FORCE_CLICK click_button=ALL_ABOUT_BOOTHILL_CLICK
) )
ASSIGNMENT_GROUP_SWITCH.add_state( ASSIGNMENT_GROUP_SWITCH.add_state(
KEYWORDS_ASSIGNMENT_GROUP.Character_Materials, KEYWORDS_ASSIGNMENT_GROUP.Character_Materials,
@ -174,7 +186,7 @@ class AssignmentUI(UI):
def _wait_until_group_loaded(self): def _wait_until_group_loaded(self):
skip_first_screenshot = True skip_first_screenshot = True
timeout = Timer(2, count=3).start() timeout = Timer(3, count=3).start()
while 1: while 1:
if skip_first_screenshot: if skip_first_screenshot:
skip_first_screenshot = False skip_first_screenshot = False
@ -201,13 +213,17 @@ class AssignmentUI(UI):
if timeout.reached(): if timeout.reached():
logger.warning('Wait entry loaded timeout') logger.warning('Wait entry loaded timeout')
break break
if self.image_color_count(ENTRY_LOADED, (35, 35, 35), count=800): if self.appear(ASSIGNMENT_CHECK) and \
self.image_color_count(ENTRY_LOADED, (35, 35, 35), count=800):
logger.info('Entry loaded') logger.info('Entry loaded')
break break
@property @property
def _limit_status(self) -> tuple[int, int, int]: def _limit_status(self) -> tuple[int, int, int]:
self.device.screenshot() self.device.screenshot()
if isinstance(ASSIGNMENT_GROUP_SWITCH.get(self), AssignmentEventGroup):
ASSIGNMENT_GROUP_SWITCH.set(
KEYWORDS_ASSIGNMENT_GROUP.Character_Materials, self)
current, remain, total = DigitCounter( current, remain, total = DigitCounter(
OCR_ASSIGNMENT_LIMIT).ocr_single_line(self.device.image) OCR_ASSIGNMENT_LIMIT).ocr_single_line(self.device.image)
if total and current <= total: if total and current <= total:

View File

@ -156,11 +156,6 @@ class CombatSupport(UI):
self.interval_reset(POPUP_CANCEL) self.interval_reset(POPUP_CANCEL)
continue continue
if self.appear(COMBAT_SUPPORT_LIST, interval=2): if self.appear(COMBAT_SUPPORT_LIST, interval=2):
scroll = AdaptiveScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area,
name=COMBAT_SUPPORT_LIST_SCROLL.name)
if not scroll.appear(main=self):
self.interval_clear(COMBAT_SUPPORT_LIST)
continue
if not selected_support and support_character_name != "FirstCharacter": if not selected_support and support_character_name != "FirstCharacter":
self._search_support(support_character_name) # Search support self._search_support(support_character_name) # Search support
selected_support = True selected_support = True

View File

@ -591,7 +591,9 @@ class DungeonUI(DungeonState):
break break
# Additional # Additional
pass # Popup that confirm character switch
if self.handle_popup_confirm('DUNGEON_ENTER'):
continue
# Click teleport # Click teleport
if self.appear(page_guide.check_button, interval=1): if self.appear(page_guide.check_button, interval=1):