Add: Select rogue path (#145)

This commit is contained in:
LmeSzinc 2023-10-15 04:20:25 +08:00
parent 18c2027e8f
commit d22efbdf53
26 changed files with 324 additions and 9 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,155 @@
from module.base.button import Button, ButtonWrapper
# This file was auto-generated, do not modify it manually. To generate:
# ``` python -m dev_tools.button_extract ```
CHECK_ABUNDANCE = ButtonWrapper(
name='CHECK_ABUNDANCE',
share=Button(
file='./assets/share/rogue/path/CHECK_ABUNDANCE.png',
area=(202, 315, 252, 365),
search=(182, 295, 272, 385),
color=(143, 120, 86),
button=(202, 315, 252, 365),
),
)
CHECK_DESTRUCTION = ButtonWrapper(
name='CHECK_DESTRUCTION',
share=Button(
file='./assets/share/rogue/path/CHECK_DESTRUCTION.png',
area=(219, 336, 269, 386),
search=(199, 316, 289, 406),
color=(131, 109, 78),
button=(219, 336, 269, 386),
),
)
CHECK_ELATION = ButtonWrapper(
name='CHECK_ELATION',
share=Button(
file='./assets/share/rogue/path/CHECK_ELATION.png',
area=(220, 309, 270, 359),
search=(200, 289, 290, 379),
color=(142, 119, 85),
button=(220, 309, 270, 359),
),
)
CHECK_NIHILITY = ButtonWrapper(
name='CHECK_NIHILITY',
share=Button(
file='./assets/share/rogue/path/CHECK_NIHILITY.png',
area=(220, 306, 270, 356),
search=(200, 286, 290, 376),
color=(130, 106, 75),
button=(220, 306, 270, 356),
),
)
CHECK_PRESERVATION = ButtonWrapper(
name='CHECK_PRESERVATION',
share=Button(
file='./assets/share/rogue/path/CHECK_PRESERVATION.png',
area=(220, 308, 270, 358),
search=(200, 288, 290, 378),
color=(144, 120, 86),
button=(220, 308, 270, 358),
),
)
CHECK_REMEMBRANCE = ButtonWrapper(
name='CHECK_REMEMBRANCE',
share=Button(
file='./assets/share/rogue/path/CHECK_REMEMBRANCE.png',
area=(220, 326, 270, 376),
search=(200, 306, 290, 396),
color=(128, 105, 75),
button=(220, 326, 270, 376),
),
)
CHECK_THE_HUNT = ButtonWrapper(
name='CHECK_THE_HUNT',
share=Button(
file='./assets/share/rogue/path/CHECK_THE_HUNT.png',
area=(221, 324, 271, 374),
search=(201, 304, 291, 394),
color=(127, 104, 74),
button=(221, 324, 271, 374),
),
)
CLICK_ABUNDANCE = ButtonWrapper(
name='CLICK_ABUNDANCE',
share=Button(
file='./assets/share/rogue/path/CLICK_ABUNDANCE.png',
area=(633, 354, 683, 404),
search=(613, 334, 703, 424),
color=(70, 70, 74),
button=(633, 354, 683, 404),
),
)
CLICK_DESTRUCTION = ButtonWrapper(
name='CLICK_DESTRUCTION',
share=Button(
file='./assets/share/rogue/path/CLICK_DESTRUCTION.png',
area=(1024, 373, 1074, 423),
search=(1004, 353, 1094, 443),
color=(64, 64, 65),
button=(1024, 373, 1074, 423),
),
)
CLICK_ELATION = ButtonWrapper(
name='CLICK_ELATION',
share=Button(
file='./assets/share/rogue/path/CLICK_ELATION.png',
area=(1185, 354, 1215, 404),
search=(1165, 334, 1235, 424),
color=(39, 40, 46),
button=(1185, 354, 1215, 404),
),
)
CLICK_NIHILITY = ButtonWrapper(
name='CLICK_NIHILITY',
share=Button(
file='./assets/share/rogue/path/CLICK_NIHILITY.png',
area=(465, 343, 515, 393),
search=(445, 323, 535, 413),
color=(57, 58, 63),
button=(465, 343, 515, 393),
),
)
CLICK_PRESERVATION = ButtonWrapper(
name='CLICK_PRESERVATION',
share=Button(
file='./assets/share/rogue/path/CLICK_PRESERVATION.png',
area=(65, 340, 88, 405),
search=(45, 320, 108, 425),
color=(31, 34, 44),
button=(65, 340, 88, 405),
),
)
CLICK_REMEMBRANCE = ButtonWrapper(
name='CLICK_REMEMBRANCE',
share=Button(
file='./assets/share/rogue/path/CLICK_REMEMBRANCE.png',
area=(278, 362, 328, 412),
search=(258, 342, 348, 432),
color=(61, 62, 69),
button=(278, 362, 328, 412),
),
)
CLICK_THE_HUNT = ButtonWrapper(
name='CLICK_THE_HUNT',
share=Button(
file='./assets/share/rogue/path/CLICK_THE_HUNT.png',
area=(837, 362, 887, 412),
search=(817, 342, 907, 432),
color=(57, 57, 61),
button=(837, 362, 887, 412),
),
)
CONFIRM_PATH = ButtonWrapper(
name='CONFIRM_PATH',
share=Button(
file='./assets/share/rogue/path/CONFIRM_PATH.png',
area=(845, 634, 868, 681),
search=(825, 614, 888, 701),
color=(178, 178, 178),
button=(865, 640, 1139, 675),
),
)

View File

@ -123,3 +123,13 @@ PAGE_EVENT = ButtonWrapper(
button=(983, 485, 1007, 509), button=(983, 485, 1007, 509),
), ),
) )
ROGUE_LAUNCH = ButtonWrapper(
name='ROGUE_LAUNCH',
share=Button(
file='./assets/share/rogue/ui/ROGUE_LAUNCH.png',
area=(875, 629, 896, 677),
search=(855, 609, 916, 697),
color=(171, 172, 172),
button=(896, 635, 1169, 671),
),
)

View File

@ -47,7 +47,10 @@ class RogueUI(UI):
return self.appear(PAGE_EVENT) return self.appear(PAGE_EVENT)
def is_page_rogue_main(self): def is_page_rogue_main(self):
return self.appear(REWARD_ENTER) return self.match_template_color(REWARD_ENTER)
def is_page_rogue_launch(self):
return self.match_template_color(ROGUE_LAUNCH)
def handle_obtain_item_popup(self, interval=5) -> bool: def handle_obtain_item_popup(self, interval=5) -> bool:
"""After selecting some curio (e.g. Sealing_Wax_of_*), there will be a popup after back to main page""" """After selecting some curio (e.g. Sealing_Wax_of_*), there will be a popup after back to main page"""

View File

@ -2,11 +2,17 @@ import tasks.rogue.keywords.blessing as KEYWORDS_ROGUE_BLESSING
import tasks.rogue.keywords.bonus as KEYWORDS_ROGUE_BONUS import tasks.rogue.keywords.bonus as KEYWORDS_ROGUE_BONUS
import tasks.rogue.keywords.curio as KEYWORDS_ROGUE_CURIO import tasks.rogue.keywords.curio as KEYWORDS_ROGUE_CURIO
import tasks.rogue.keywords.enhancement as KEYWORDS_ROGUE_ENHANCEMENT import tasks.rogue.keywords.enhancement as KEYWORDS_ROGUE_ENHANCEMENT
import tasks.rogue.keywords.event_option as KEYWORDS_ROGUE_EVENT_OPTION
import tasks.rogue.keywords.event_title as KEYWORDS_ROGUE_EVENT_TITLE
import tasks.rogue.keywords.path as KEYWORDS_ROGUE_PATH import tasks.rogue.keywords.path as KEYWORDS_ROGUE_PATH
import tasks.rogue.keywords.resonance as KEYWORDS_ROGUE_RESONANCE import tasks.rogue.keywords.resonance as KEYWORDS_ROGUE_RESONANCE
import tasks.rogue.keywords.event_title as KEYWORDS_ROGUE_EVENT_TITLE from tasks.rogue.keywords.classes import (
import tasks.rogue.keywords.event_option as KEYWORDS_ROGUE_EVENT_OPTION RogueBlessing,
from tasks.rogue.keywords.classes import (RogueBlessing, RogueBonus, RogueBonus,
RogueCurio, RogueEnhancement, RogueCurio,
RoguePath, RogueResonance, RogueEnhancement,
RogueEventTitle, RogueEventOption) RogueEventOption,
RogueEventTitle,
RoguePath,
RogueResonance
)

View File

@ -27,6 +27,9 @@ class RogueBlessing(Keyword):
class RoguePath(Keyword): class RoguePath(Keyword):
instances: ClassVar = {} instances: ClassVar = {}
def __hash__(self) -> int:
return super().__hash__()
@property @property
def path_name(self): def path_name(self):
return [self.__getattribute__(f"{server}_parsed").replace("the", '') return [self.__getattribute__(f"{server}_parsed").replace("the", '')

136
tasks/rogue/path.py Normal file
View File

@ -0,0 +1,136 @@
from typing import Dict, Optional
from module.base.decorator import cached_property
from module.base.timer import Timer
from module.exception import ScriptError
from module.logger import logger
from tasks.base.assets.assets_base_page import BACK
from tasks.rogue.assets.assets_rogue_path import *
from tasks.rogue.assets.assets_rogue_ui import ROGUE_LAUNCH
from tasks.rogue.bleesing.ui import RogueUI
from tasks.rogue.keywords import KEYWORDS_ROGUE_PATH, RoguePath
def area_pad_around(area, pad):
"""
Inner offset an area.
Args:
area: (upper_left_x, upper_left_y, bottom_right_x, bottom_right_y).
pad (tuple):
Returns:
tuple: (upper_left_x, upper_left_y, bottom_right_x, bottom_right_y).
"""
upper_left_x, upper_left_y, bottom_right_x, bottom_right_y = area
upper_left_x_pad, upper_left_y_pad, bottom_right_x_pad, bottom_right_y_pad = pad
return upper_left_x + upper_left_x_pad, \
upper_left_y + upper_left_y_pad, \
bottom_right_x - bottom_right_x_pad, \
bottom_right_y - bottom_right_y_pad
class RoguePathHandler(RogueUI):
@cached_property
def _rogue_path_checks(self) -> Dict[RoguePath, ButtonWrapper]:
buttons = {
KEYWORDS_ROGUE_PATH.Preservation: CHECK_PRESERVATION,
KEYWORDS_ROGUE_PATH.Remembrance: CHECK_REMEMBRANCE,
KEYWORDS_ROGUE_PATH.Nihility: CHECK_NIHILITY,
KEYWORDS_ROGUE_PATH.Abundance: CHECK_ABUNDANCE,
KEYWORDS_ROGUE_PATH.The_Hunt: CHECK_THE_HUNT,
KEYWORDS_ROGUE_PATH.Destruction: CHECK_DESTRUCTION,
KEYWORDS_ROGUE_PATH.Elation: CHECK_ELATION,
}
return buttons
@cached_property
def _rogue_path_clicks(self) -> Dict[RoguePath, ButtonWrapper]:
buttons = {
KEYWORDS_ROGUE_PATH.Preservation: CLICK_PRESERVATION,
KEYWORDS_ROGUE_PATH.Remembrance: CLICK_REMEMBRANCE,
KEYWORDS_ROGUE_PATH.Nihility: CLICK_NIHILITY,
KEYWORDS_ROGUE_PATH.Abundance: CLICK_ABUNDANCE,
KEYWORDS_ROGUE_PATH.The_Hunt: CLICK_THE_HUNT,
KEYWORDS_ROGUE_PATH.Destruction: CLICK_DESTRUCTION,
KEYWORDS_ROGUE_PATH.Elation: CLICK_ELATION,
}
# Path list is sliding, expand search area
for b in buttons.values():
b.load_search(area_pad_around(b.area, pad=(-100, -5, -100, -5)))
return buttons
def _get_path_click(self, path: RoguePath) -> ButtonWrapper:
try:
return self._rogue_path_clicks[path]
except KeyError:
logger.critical(f'Invalid rogue path: {path}')
raise ScriptError
def _get_selected_path(self, skip_first_screenshot=True) -> Optional[RoguePath]:
timeout = Timer(1, count=5).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if timeout.reached():
break
for path, button in self._rogue_path_checks.items():
# Check colors to wait appear animation
if self.match_template_color(button):
logger.attr('SelectPath', path)
return path
logger.warning('Unable to get select path')
return None
def _is_page_rogue_path(self) -> bool:
appear = [self.appear(button) for button in self._rogue_path_clicks.values()]
return all(appear)
def rogue_path_select(self, path: str | RoguePath, skip_first_screenshot=True):
"""
Pages:
in: LAUNCH_ROGUE
out: is_page_choose_bonus()
or page_main if previous rogue run had bonus selected but didn't finish any domain
"""
logger.hr('Rogue path select', level=2)
path: RoguePath = RoguePath.find(path)
logger.info(f'Select path: {path}')
entry = self._get_path_click(path)
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.is_page_choose_bonus():
logger.info('rogue_path_select ended at is_page_choose_bonus')
break
if self.is_in_main():
logger.info('rogue_path_select ended at page_main')
break
if self.appear_then_click(ROGUE_LAUNCH, interval=2):
continue
# The average level of your team is lower than the recommended level.
# Continue anyway?
if self.handle_popup_confirm():
continue
# Select path
if self.interval_is_reached(entry) and self._is_page_rogue_path():
if self.appear_then_click(entry):
self.interval_reset(entry)
# Confirm path
if self.appear(CONFIRM_PATH, interval=2):
if self._get_selected_path() == path:
self.device.click(CONFIRM_PATH)
continue
else:
logger.warning('Selected to the wrong path')
self.device.click(BACK)
continue

View File

@ -104,8 +104,8 @@ class RogueRewardHandler(RogueUI):
in: is_page_rogue_main() in: is_page_rogue_main()
out: is_page_rogue_main() out: is_page_rogue_main()
""" """
logger.hr('Rogue reward claim', level=2)
if self._rogue_reward_appear(): if self._rogue_reward_appear():
logger.hr('Rogue reward claim', level=2)
self._rogue_reward_enter() self._rogue_reward_enter()
self._rogue_reward_claim() self._rogue_reward_claim()
self._rogue_reward_exit() self._rogue_reward_exit()

View File

@ -1,8 +1,9 @@
from tasks.rogue.path import RoguePathHandler
from tasks.rogue.reward import RogueRewardHandler from tasks.rogue.reward import RogueRewardHandler
from tasks.rogue.route.loader import RouteLoader from tasks.rogue.route.loader import RouteLoader
class RogueHandler(RouteLoader, RogueRewardHandler): class RogueHandler(RouteLoader, RogueRewardHandler, RoguePathHandler):
def rogue_once(self): def rogue_once(self):
""" """
Do a complete rogue run. Do a complete rogue run.
@ -11,6 +12,7 @@ class RogueHandler(RouteLoader, RogueRewardHandler):
in: page_rogue, is_page_rogue_main() in: page_rogue, is_page_rogue_main()
out: page_rogue, is_page_rogue_main() out: page_rogue, is_page_rogue_main()
""" """
self.rogue_path_select(self.config.RoguePath_Path)
self.rogue_run() self.rogue_run()
self.rogue_reward_claim() self.rogue_reward_claim()