Merge pull request #198 from Yinhaoran1128/dev

Upd: Use DraggableList to rewrite choose rogue path and add propagation in rogue
This commit is contained in:
LmeSzinc 2023-12-11 01:03:31 +08:00 committed by GitHub
commit 986a90c18a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 121 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1208,7 +1208,8 @@
"Abundance", "Abundance",
"The_Hunt", "The_Hunt",
"Destruction", "Destruction",
"Elation" "Elation",
"Propagation"
] ]
}, },
"Bonus": { "Bonus": {

View File

@ -212,7 +212,7 @@ RogueWorld:
] ]
Path: Path:
value: The_Hunt value: The_Hunt
option: [ Preservation, Remembrance, Nihility, Abundance, The_Hunt, Destruction, Elation ] option: [ Preservation, Remembrance, Nihility, Abundance, The_Hunt, Destruction, Elation, Propagation ]
Bonus: Bonus:
value: Blessing Cosmos value: Blessing Cosmos
option: [ Blessing Cosmos, Miracle Cosmos, Fragmented Cosmos ] option: [ Blessing Cosmos, Miracle Cosmos, Fragmented Cosmos ]

View File

@ -119,7 +119,7 @@ class GeneratedConfig:
# Group `RogueWorld` # Group `RogueWorld`
RogueWorld_World = 'Simulated_Universe_World_7' # Simulated_Universe_World_3, Simulated_Universe_World_4, Simulated_Universe_World_5, Simulated_Universe_World_6, Simulated_Universe_World_7, Simulated_Universe_World_8 RogueWorld_World = 'Simulated_Universe_World_7' # Simulated_Universe_World_3, Simulated_Universe_World_4, Simulated_Universe_World_5, Simulated_Universe_World_6, Simulated_Universe_World_7, Simulated_Universe_World_8
RogueWorld_Path = 'The_Hunt' # Preservation, Remembrance, Nihility, Abundance, The_Hunt, Destruction, Elation RogueWorld_Path = 'The_Hunt' # Preservation, Remembrance, Nihility, Abundance, The_Hunt, Destruction, Elation, Propagation
RogueWorld_Bonus = 'Blessing Cosmos' # Blessing Cosmos, Miracle Cosmos, Fragmented Cosmos RogueWorld_Bonus = 'Blessing Cosmos' # Blessing Cosmos, Miracle Cosmos, Fragmented Cosmos
RogueWorld_DomainStrategy = 'combat' # combat, occurrence RogueWorld_DomainStrategy = 'combat' # combat, occurrence
RogueWorld_UseImmersifier = True RogueWorld_UseImmersifier = True

View File

@ -806,7 +806,8 @@
"Abundance": "Abundance", "Abundance": "Abundance",
"The_Hunt": "The Hunt", "The_Hunt": "The Hunt",
"Destruction": "Destruction", "Destruction": "Destruction",
"Elation": "Elation" "Elation": "Elation",
"Propagation": "Propagation"
}, },
"Bonus": { "Bonus": {
"name": "Blessings of Trailblaze", "name": "Blessings of Trailblaze",

View File

@ -806,7 +806,8 @@
"Abundance": "Abundancia", "Abundance": "Abundancia",
"The_Hunt": "Cacería", "The_Hunt": "Cacería",
"Destruction": "Destrucción", "Destruction": "Destrucción",
"Elation": "Exultación" "Elation": "Exultación",
"Propagation": "Propagación"
}, },
"Bonus": { "Bonus": {
"name": "Bendiciones", "name": "Bendiciones",

View File

@ -806,7 +806,8 @@
"Abundance": "Abundance", "Abundance": "Abundance",
"The_Hunt": "The_Hunt", "The_Hunt": "The_Hunt",
"Destruction": "Destruction", "Destruction": "Destruction",
"Elation": "Elation" "Elation": "Elation",
"Propagation": "Propagation"
}, },
"Bonus": { "Bonus": {
"name": "RogueWorld.Bonus.name", "name": "RogueWorld.Bonus.name",

View File

@ -806,7 +806,8 @@
"Abundance": "丰饶", "Abundance": "丰饶",
"The_Hunt": "巡猎", "The_Hunt": "巡猎",
"Destruction": "毁灭", "Destruction": "毁灭",
"Elation": "欢愉" "Elation": "欢愉",
"Propagation": "繁育"
}, },
"Bonus": { "Bonus": {
"name": "开拓祝福三选一", "name": "开拓祝福三选一",

View File

@ -806,7 +806,8 @@
"Abundance": "豐饒", "Abundance": "豐饒",
"The_Hunt": "巡獵", "The_Hunt": "巡獵",
"Destruction": "毀滅", "Destruction": "毀滅",
"Elation": "歡愉" "Elation": "歡愉",
"Propagation": "繁育"
}, },
"Bonus": { "Bonus": {
"name": "開拓祝福三選一", "name": "開拓祝福三選一",

View File

@ -63,6 +63,16 @@ CHECK_PRESERVATION = ButtonWrapper(
button=(220, 308, 270, 358), button=(220, 308, 270, 358),
), ),
) )
CHECK_PROPAGATION = ButtonWrapper(
name='CHECK_PROPAGATION',
share=Button(
file='./assets/share/rogue/path/CHECK_PROPAGATION.png',
area=(206, 308, 286, 372),
search=(186, 288, 306, 392),
color=(126, 104, 75),
button=(206, 308, 286, 372),
),
)
CHECK_REMEMBRANCE = ButtonWrapper( CHECK_REMEMBRANCE = ButtonWrapper(
name='CHECK_REMEMBRANCE', name='CHECK_REMEMBRANCE',
share=Button( share=Button(
@ -83,6 +93,26 @@ CHECK_THE_HUNT = ButtonWrapper(
button=(221, 324, 271, 374), button=(221, 324, 271, 374),
), ),
) )
CHOOSE_LEFT = ButtonWrapper(
name='CHOOSE_LEFT',
share=Button(
file='./assets/share/rogue/path/CHOOSE_LEFT.png',
area=(44, 292, 102, 365),
search=(24, 272, 122, 385),
color=(30, 33, 42),
button=(44, 292, 102, 365),
),
)
CHOOSE_RIGHT = ButtonWrapper(
name='CHOOSE_RIGHT',
share=Button(
file='./assets/share/rogue/path/CHOOSE_RIGHT.png',
area=(1177, 291, 1236, 364),
search=(1157, 271, 1256, 384),
color=(32, 33, 39),
button=(1177, 291, 1236, 364),
),
)
CLICK_ABUNDANCE = ButtonWrapper( CLICK_ABUNDANCE = ButtonWrapper(
name='CLICK_ABUNDANCE', name='CLICK_ABUNDANCE',
share=Button( share=Button(
@ -163,3 +193,20 @@ CONFIRM_PATH = ButtonWrapper(
button=(865, 640, 1139, 675), button=(865, 640, 1139, 675),
), ),
) )
PAGE_ROGUE_PATH = ButtonWrapper(
name='PAGE_ROGUE_PATH',
cn=Button(
file='./assets/cn/rogue/path/PAGE_ROGUE_PATH.png',
area=(713, 87, 759, 109),
search=(693, 67, 779, 129),
color=(122, 120, 119),
button=(713, 87, 759, 109),
),
en=Button(
file='./assets/en/rogue/path/PAGE_ROGUE_PATH.png',
area=(606, 89, 656, 108),
search=(586, 69, 676, 128),
color=(114, 112, 112),
button=(606, 89, 656, 108),
),
)

View File

@ -40,6 +40,7 @@ class RoguePathHandler(RogueUI):
KEYWORDS_ROGUE_PATH.The_Hunt: CHECK_THE_HUNT, KEYWORDS_ROGUE_PATH.The_Hunt: CHECK_THE_HUNT,
KEYWORDS_ROGUE_PATH.Destruction: CHECK_DESTRUCTION, KEYWORDS_ROGUE_PATH.Destruction: CHECK_DESTRUCTION,
KEYWORDS_ROGUE_PATH.Elation: CHECK_ELATION, KEYWORDS_ROGUE_PATH.Elation: CHECK_ELATION,
KEYWORDS_ROGUE_PATH.Propagation: CHECK_PROPAGATION
} }
return buttons return buttons
@ -60,11 +61,28 @@ class RoguePathHandler(RogueUI):
return buttons return buttons
def _get_path_click(self, path: RoguePath) -> ButtonWrapper: def _get_path_click(self, path: RoguePath) -> ButtonWrapper:
try: buttons = self._rogue_path_clicks
return self._rogue_path_clicks[path] if ret := buttons.get(path):
except KeyError: return ret
logger.critical(f'Invalid rogue path: {path}') else:
raise ScriptError # choose the closest path
paths = list(buttons.keys())
path_click = min(paths, key=lambda p: min(self._calculate_distance(p, path)))
return buttons.get(path_click)
@staticmethod
def _calculate_distance(path_1: RoguePath, path_2: RoguePath):
"""
click times from path1 to path2
Returns:
tuple: (left_times, right_times)
"""
length = len(path_1.instances)
distance = path_1.id - path_2.id
left_times = distance % length
right_times = -distance % length
return left_times, right_times
def _get_selected_path(self, skip_first_screenshot=True) -> RoguePath | None: def _get_selected_path(self, skip_first_screenshot=True) -> RoguePath | None:
timeout = Timer(1, count=5).start() timeout = Timer(1, count=5).start()
@ -86,8 +104,8 @@ class RoguePathHandler(RogueUI):
return None return None
def _is_page_rogue_path(self) -> bool: def _is_page_rogue_path(self) -> bool:
appear = [self.appear(button) for button in self._rogue_path_clicks.values()] appear = self.appear(PAGE_ROGUE_PATH)
return all(appear) return appear
def _is_team_prepared(self) -> bool: def _is_team_prepared(self) -> bool:
""" """
@ -99,6 +117,30 @@ class RoguePathHandler(RogueUI):
logger.attr('TeamSlotsPrepared', slots) logger.attr('TeamSlotsPrepared', slots)
return slots > 0 return slots > 0
def _change_confirm_path(self, path: RoguePath, skip_first_screenshot=True) -> bool:
timeout = Timer(20, count=10).start()
selected_path_last = None
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
selected_path = self._get_selected_path()
if selected_path == path:
return True
elif selected_path != selected_path_last:
left_times, right_times = self._calculate_distance(selected_path, path)
if left_times <= right_times:
self.device.click(CHOOSE_LEFT)
else:
self.device.click(CHOOSE_RIGHT)
if timeout.reached():
break
selected_path_last = selected_path
logger.warning('Unable to change into chosen path')
return False
def rogue_path_select(self, path: str | RoguePath, skip_first_screenshot=True): def rogue_path_select(self, path: str | RoguePath, skip_first_screenshot=True):
""" """
Raises: Raises:
@ -110,7 +152,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: RoguePath = RoguePath.find_path(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:
@ -143,10 +185,6 @@ class RoguePathHandler(RogueUI):
continue continue
# Confirm path # Confirm path
if self.appear(CONFIRM_PATH, interval=2): if self.appear(CONFIRM_PATH, interval=2):
if self._get_selected_path() == path: if self._change_confirm_path(path):
self.device.click(CONFIRM_PATH) self.device.click(CONFIRM_PATH)
continue continue
else:
logger.warning('Selected to the wrong path')
self.device.click(BACK)
continue

View File

@ -2,6 +2,7 @@ from dataclasses import dataclass
from typing import ClassVar from typing import ClassVar
from dev_tools.keyword_extract import UI_LANGUAGES from dev_tools.keyword_extract import UI_LANGUAGES
from module.exception import ScriptError
from module.ocr.keyword import Keyword from module.ocr.keyword import Keyword
@ -35,6 +36,14 @@ 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):
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):