2023-10-17 04:45:12 +00:00
|
|
|
|
import re
|
|
|
|
|
|
2024-02-06 21:52:57 +00:00
|
|
|
|
import cv2
|
2023-05-22 17:00:20 +00:00
|
|
|
|
import numpy as np
|
|
|
|
|
|
2023-06-20 02:55:32 +00:00
|
|
|
|
from module.base.base import ModuleBase
|
2023-06-14 16:15:14 +00:00
|
|
|
|
from module.base.button import ClickButton
|
2023-05-22 17:00:20 +00:00
|
|
|
|
from module.base.timer import Timer
|
|
|
|
|
from module.base.utils import get_color
|
2023-11-02 10:56:20 +00:00
|
|
|
|
from module.exception import ScriptError
|
2023-05-22 17:00:20 +00:00
|
|
|
|
from module.logger import logger
|
2023-11-01 19:56:01 +00:00
|
|
|
|
from module.ocr.ocr import Ocr, OcrResultButton
|
2024-01-29 15:15:01 +00:00
|
|
|
|
from module.ocr.utils import split_and_pair_button_attr, split_and_pair_buttons
|
2023-05-30 18:20:45 +00:00
|
|
|
|
from module.ui.draggable_list import DraggableList
|
2023-05-22 17:00:20 +00:00
|
|
|
|
from module.ui.switch import Switch
|
|
|
|
|
from tasks.base.page import page_guide
|
2023-11-02 10:56:20 +00:00
|
|
|
|
from tasks.combat.assets.assets_combat_interact import DUNGEON_COMBAT_INTERACT, DUNGEON_COMBAT_INTERACT_TEXT
|
2023-06-14 16:15:14 +00:00
|
|
|
|
from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE
|
2023-05-22 17:00:20 +00:00
|
|
|
|
from tasks.dungeon.assets.assets_dungeon_ui import *
|
2023-06-14 16:15:14 +00:00
|
|
|
|
from tasks.dungeon.keywords import (
|
|
|
|
|
DungeonList,
|
|
|
|
|
DungeonNav,
|
|
|
|
|
DungeonTab,
|
|
|
|
|
KEYWORDS_DUNGEON_ENTRANCE,
|
2023-11-02 10:56:20 +00:00
|
|
|
|
KEYWORDS_DUNGEON_LIST,
|
2023-06-14 16:15:14 +00:00
|
|
|
|
KEYWORDS_DUNGEON_NAV,
|
|
|
|
|
KEYWORDS_DUNGEON_TAB
|
|
|
|
|
)
|
|
|
|
|
from tasks.dungeon.keywords.classes import DungeonEntrance
|
2023-11-01 19:56:01 +00:00
|
|
|
|
from tasks.dungeon.state import DungeonState
|
2024-02-06 21:52:57 +00:00
|
|
|
|
from tasks.map.interact.aim import inrange
|
2024-02-06 22:57:52 +00:00
|
|
|
|
from tasks.map.keywords import KEYWORDS_MAP_WORLD, MapPlane
|
2023-05-22 17:00:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DungeonTabSwitch(Switch):
|
|
|
|
|
def click(self, state, main):
|
|
|
|
|
"""
|
|
|
|
|
Args:
|
|
|
|
|
state (str):
|
|
|
|
|
main (ModuleBase):
|
|
|
|
|
"""
|
|
|
|
|
button = self.get_data(state)['click_button']
|
|
|
|
|
_ = main.appear(button) # Search button to load offset
|
|
|
|
|
main.device.click(button)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DUNGEON_TAB = DungeonTabSwitch('DungeonTab', is_selector=True)
|
|
|
|
|
SWITCH_DUNGEON_TAB.add_state(
|
|
|
|
|
KEYWORDS_DUNGEON_TAB.Operation_Briefing,
|
|
|
|
|
check_button=OPERATION_BRIEFING_CHECK,
|
|
|
|
|
click_button=OPERATION_BRIEFING_CLICK
|
|
|
|
|
)
|
|
|
|
|
SWITCH_DUNGEON_TAB.add_state(
|
|
|
|
|
KEYWORDS_DUNGEON_TAB.Daily_Training,
|
|
|
|
|
check_button=DAILY_TRAINING_CHECK,
|
|
|
|
|
click_button=DAILY_TRAINING_CLICK
|
|
|
|
|
)
|
|
|
|
|
SWITCH_DUNGEON_TAB.add_state(
|
|
|
|
|
KEYWORDS_DUNGEON_TAB.Survival_Index,
|
|
|
|
|
check_button=SURVIVAL_INDEX_CHECK,
|
|
|
|
|
click_button=SURVIVAL_INDEX_CLICK
|
|
|
|
|
)
|
2023-12-27 12:41:57 +00:00
|
|
|
|
SWITCH_DUNGEON_TAB.add_state(
|
|
|
|
|
KEYWORDS_DUNGEON_TAB.Treasures_Lightward,
|
|
|
|
|
check_button=TREASURES_LIGHTWARD_CHECK,
|
|
|
|
|
click_button=TREASURES_LIGHTWARD_CLICK
|
|
|
|
|
)
|
2023-06-14 16:15:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OcrDungeonNav(Ocr):
|
|
|
|
|
def after_process(self, result):
|
|
|
|
|
result = super().after_process(result)
|
2023-07-10 15:36:35 +00:00
|
|
|
|
result = result.replace('#', '')
|
2023-09-08 14:23:57 +00:00
|
|
|
|
if self.lang == 'cn':
|
2023-06-14 16:15:14 +00:00
|
|
|
|
result = result.replace('萼喜', '萼')
|
2023-06-27 18:26:32 +00:00
|
|
|
|
result = result.replace('带', '滞') # 凝带虚影
|
2023-06-14 16:15:14 +00:00
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OcrDungeonList(Ocr):
|
2023-07-04 10:20:03 +00:00
|
|
|
|
def after_process(self, result):
|
2024-02-06 21:24:46 +00:00
|
|
|
|
# 乙太之蕾•雅利洛-Ⅵ
|
2024-02-13 11:05:33 +00:00
|
|
|
|
result = re.sub(r'-[VⅤ][IⅠ]', '-Ⅵ', result)
|
2024-02-06 21:24:46 +00:00
|
|
|
|
|
2024-05-09 09:40:41 +00:00
|
|
|
|
# 苏乐达™热砂海选会场
|
|
|
|
|
result = re.sub(r'(苏乐达|蘇樂達|SoulGlad|スラーダ|FelizAlma)[rtT]*M', r'\1', result)
|
|
|
|
|
|
2023-07-04 10:20:03 +00:00
|
|
|
|
result = super().after_process(result)
|
2024-02-06 21:24:46 +00:00
|
|
|
|
|
2023-09-08 14:23:57 +00:00
|
|
|
|
if self.lang == 'cn':
|
2023-07-04 10:20:03 +00:00
|
|
|
|
result = result.replace('翼', '巽') # 巽风之形
|
2023-07-06 18:22:20 +00:00
|
|
|
|
result = result.replace('皖A0', '50').replace('皖', '')
|
2023-10-16 11:13:13 +00:00
|
|
|
|
# 燔灼之形•凝滞虚影
|
|
|
|
|
result = result.replace('熠', '燔')
|
2023-10-17 04:45:12 +00:00
|
|
|
|
result = re.sub('^灼之形', '燔灼之形', result)
|
2024-04-25 04:05:04 +00:00
|
|
|
|
# 偃偶之形•凝滞虚影
|
|
|
|
|
result = re.sub('^偶之形', '偃偶之形', result)
|
2023-12-27 17:41:04 +00:00
|
|
|
|
# 蛀星的旧·历战余响
|
|
|
|
|
result = re.sub(r'蛀星的旧.*?历战', '蛀星的旧靥•历战', result)
|
2024-02-06 22:57:52 +00:00
|
|
|
|
|
|
|
|
|
# 9支援仓段
|
2024-02-17 13:27:27 +00:00
|
|
|
|
for word in 'Q9α':
|
|
|
|
|
result = result.removeprefix(word)
|
2023-07-04 10:20:03 +00:00
|
|
|
|
return result
|
2023-06-14 16:15:14 +00:00
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
|
|
2024-02-06 22:57:52 +00:00
|
|
|
|
class OcrDungeonListCalyxCrimson(OcrDungeonList):
|
|
|
|
|
def _match_result(self, *args, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Convert MapPlane object to their corresponding DungeonList object
|
|
|
|
|
"""
|
|
|
|
|
plane = super()._match_result(*args, **kwargs)
|
|
|
|
|
if plane is not None:
|
|
|
|
|
for dungeon in DungeonList.instances.values():
|
|
|
|
|
if dungeon.is_Calyx_Crimson and dungeon.plane == plane:
|
|
|
|
|
return dungeon
|
|
|
|
|
return plane
|
|
|
|
|
|
|
|
|
|
|
2023-06-14 16:15:14 +00:00
|
|
|
|
class OcrDungeonListLimitEntrance(OcrDungeonList):
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
self.button = ClickButton((*self.button.area[:3], self.button.area[3] - 70))
|
|
|
|
|
|
|
|
|
|
|
2024-02-18 17:43:05 +00:00
|
|
|
|
class OcrDungeonListCalyxCrimsonLimitEntrance(OcrDungeonListCalyxCrimson, OcrDungeonListLimitEntrance):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
|
class DraggableDungeonNav(DraggableList):
|
|
|
|
|
# 0.5 is the magic number to reach bottom in 1 swipe
|
|
|
|
|
# but relax we still have retires when magic doesn't work
|
|
|
|
|
drag_vector = (0.50, 0.52)
|
|
|
|
|
|
|
|
|
|
|
2023-06-20 02:55:32 +00:00
|
|
|
|
class DraggableDungeonList(DraggableList):
|
|
|
|
|
teleports: list[OcrResultButton] = []
|
|
|
|
|
navigates: list[OcrResultButton] = []
|
|
|
|
|
|
2024-02-07 04:41:53 +00:00
|
|
|
|
# use_plane: True to use map planes to predict dungeons only.
|
|
|
|
|
# Can only be True in Calyx Crimson
|
|
|
|
|
use_plane = False
|
2024-02-18 17:43:05 +00:00
|
|
|
|
# limit_entrance: True to ensure the teleport button is insight
|
|
|
|
|
limit_entrance = False
|
2024-02-07 04:41:53 +00:00
|
|
|
|
|
|
|
|
|
def load_rows(self, main: ModuleBase, allow_early_access=False):
|
2024-01-29 15:15:01 +00:00
|
|
|
|
"""
|
|
|
|
|
Args:
|
|
|
|
|
main:
|
|
|
|
|
allow_early_access: True to allow dungeons that are in temporarily early access during events
|
|
|
|
|
"""
|
|
|
|
|
relative_area = (0, 0, 1280, 120)
|
2024-02-07 04:41:53 +00:00
|
|
|
|
if self.use_plane:
|
2024-02-06 22:57:52 +00:00
|
|
|
|
self.keyword_class = [MapPlane, DungeonEntrance]
|
2024-02-18 17:43:05 +00:00
|
|
|
|
if self.limit_entrance:
|
|
|
|
|
self.ocr_class = OcrDungeonListCalyxCrimsonLimitEntrance
|
|
|
|
|
else:
|
|
|
|
|
self.ocr_class = OcrDungeonListCalyxCrimson
|
2024-02-06 22:57:52 +00:00
|
|
|
|
else:
|
|
|
|
|
self.keyword_class = [DungeonList, DungeonEntrance]
|
2024-02-18 17:43:05 +00:00
|
|
|
|
if self.limit_entrance:
|
|
|
|
|
self.ocr_class = OcrDungeonListLimitEntrance
|
|
|
|
|
else:
|
|
|
|
|
self.ocr_class = OcrDungeonList
|
2023-06-20 02:55:32 +00:00
|
|
|
|
super().load_rows(main=main)
|
2024-01-29 15:15:01 +00:00
|
|
|
|
|
|
|
|
|
# Check early access dungeons
|
|
|
|
|
buttons = DUNGEON_LIST.cur_buttons.copy()
|
|
|
|
|
for name, button in split_and_pair_buttons(
|
|
|
|
|
DUNGEON_LIST.cur_buttons,
|
|
|
|
|
split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Enter,
|
|
|
|
|
relative_area=relative_area
|
|
|
|
|
):
|
|
|
|
|
logger.warning(f'Early access dungeon: {name}')
|
|
|
|
|
buttons.remove(name)
|
|
|
|
|
buttons.remove(button)
|
|
|
|
|
|
|
|
|
|
# Remove early access dungeons
|
|
|
|
|
if not allow_early_access:
|
|
|
|
|
DUNGEON_LIST.cur_buttons = buttons
|
|
|
|
|
# From super.load_rows(), re-calculate indexes
|
|
|
|
|
indexes = [self.keyword2index(row.matched_keyword)
|
|
|
|
|
for row in self.cur_buttons]
|
|
|
|
|
indexes = [index for index in indexes if index]
|
2024-02-17 16:10:49 +00:00
|
|
|
|
|
|
|
|
|
if not indexes:
|
|
|
|
|
logger.warning(f'No valid rows loaded into {self}')
|
|
|
|
|
return
|
|
|
|
|
|
2024-01-29 15:15:01 +00:00
|
|
|
|
self.cur_min = min(indexes)
|
|
|
|
|
self.cur_max = max(indexes)
|
|
|
|
|
logger.attr(self.name, f'{self.cur_min} - {self.cur_max}')
|
|
|
|
|
|
2023-06-20 02:55:32 +00:00
|
|
|
|
# Replace dungeon.button with teleport
|
|
|
|
|
self.teleports = list(split_and_pair_button_attr(
|
|
|
|
|
DUNGEON_LIST.cur_buttons,
|
2024-01-28 05:45:04 +00:00
|
|
|
|
split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Teleport and x != KEYWORDS_DUNGEON_ENTRANCE.Enter,
|
2024-01-29 15:15:01 +00:00
|
|
|
|
relative_area=relative_area
|
2023-06-20 02:55:32 +00:00
|
|
|
|
))
|
|
|
|
|
self.navigates = list(split_and_pair_button_attr(
|
|
|
|
|
DUNGEON_LIST.cur_buttons,
|
|
|
|
|
split_func=lambda x: x != KEYWORDS_DUNGEON_ENTRANCE.Navigate,
|
2024-01-29 15:15:01 +00:00
|
|
|
|
relative_area=relative_area
|
2023-06-20 02:55:32 +00:00
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
|
DUNGEON_NAV_LIST = DraggableDungeonNav(
|
2023-06-14 16:15:14 +00:00
|
|
|
|
'DungeonNavList', keyword_class=DungeonNav, ocr_class=OcrDungeonNav, search_button=OCR_DUNGEON_NAV)
|
2023-06-20 02:55:32 +00:00
|
|
|
|
DUNGEON_LIST = DraggableDungeonList(
|
2024-02-06 22:57:52 +00:00
|
|
|
|
'DungeonList', keyword_class=[DungeonList, DungeonEntrance, MapPlane],
|
2023-06-14 16:15:14 +00:00
|
|
|
|
ocr_class=OcrDungeonList, search_button=OCR_DUNGEON_LIST)
|
2023-05-22 17:00:20 +00:00
|
|
|
|
|
|
|
|
|
|
2023-11-02 17:55:28 +00:00
|
|
|
|
class DungeonUI(DungeonState):
|
2023-05-22 17:00:20 +00:00
|
|
|
|
def dungeon_tab_goto(self, state: DungeonTab):
|
|
|
|
|
"""
|
|
|
|
|
Args:
|
|
|
|
|
state:
|
|
|
|
|
|
2023-07-06 18:22:20 +00:00
|
|
|
|
Returns:
|
|
|
|
|
bool: If UI switched
|
|
|
|
|
|
2023-05-22 17:00:20 +00:00
|
|
|
|
Examples:
|
|
|
|
|
self = DungeonUI('alas')
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Operation_Briefing)
|
|
|
|
|
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Daily_Training)
|
|
|
|
|
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
|
|
|
|
"""
|
2023-06-14 16:15:14 +00:00
|
|
|
|
logger.hr('Dungeon tab goto', level=2)
|
2023-07-06 18:22:20 +00:00
|
|
|
|
ui_switched = self.ui_ensure(page_guide)
|
|
|
|
|
tab_switched = SWITCH_DUNGEON_TAB.set(state, main=self)
|
|
|
|
|
|
|
|
|
|
if ui_switched or tab_switched:
|
2023-06-14 16:15:14 +00:00
|
|
|
|
if state == KEYWORDS_DUNGEON_TAB.Daily_Training:
|
|
|
|
|
logger.info(f'Tab goto {state}, wait until loaded')
|
|
|
|
|
self._dungeon_wait_daily_training_loaded()
|
|
|
|
|
elif state == KEYWORDS_DUNGEON_TAB.Survival_Index:
|
|
|
|
|
logger.info(f'Tab goto {state}, wait until loaded')
|
2023-12-27 12:41:57 +00:00
|
|
|
|
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()
|
2023-07-06 18:22:20 +00:00
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
2023-05-22 17:00:20 +00:00
|
|
|
|
|
|
|
|
|
def _dungeon_wait_daily_training_loaded(self, skip_first_screenshot=True):
|
2023-07-06 14:41:16 +00:00
|
|
|
|
"""
|
|
|
|
|
Returns:
|
|
|
|
|
bool: True if wait success, False if wait timeout.
|
|
|
|
|
|
|
|
|
|
Pages:
|
|
|
|
|
in: page_guide, Daily_Training
|
|
|
|
|
"""
|
2023-05-22 17:00:20 +00:00
|
|
|
|
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 daily training loaded timeout')
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return False
|
2023-05-22 17:00:20 +00:00
|
|
|
|
color = get_color(self.device.image, DAILY_TRAINING_LOADED.area)
|
|
|
|
|
if np.mean(color) < 128:
|
|
|
|
|
logger.info('Daily training loaded')
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return True
|
2023-05-22 17:00:20 +00:00
|
|
|
|
|
2023-12-27 12:41:57 +00:00
|
|
|
|
def _dungeon_wait_survival_index_loaded(self, skip_first_screenshot=True):
|
2023-07-06 14:41:16 +00:00
|
|
|
|
"""
|
|
|
|
|
Returns:
|
|
|
|
|
bool: True if wait success, False if wait timeout.
|
|
|
|
|
|
|
|
|
|
Pages:
|
|
|
|
|
in: page_guide, Survival_Index
|
|
|
|
|
"""
|
2023-05-22 17:00:20 +00:00
|
|
|
|
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 survival index loaded timeout')
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return False
|
2023-05-22 17:00:20 +00:00
|
|
|
|
if self.appear(SURVIVAL_INDEX_LOADED):
|
|
|
|
|
logger.info('Survival index loaded')
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return True
|
|
|
|
|
|
2023-12-27 12:41:57 +00:00
|
|
|
|
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()
|
2024-02-06 07:58:34 +00:00
|
|
|
|
TREASURES_LIGHTWARD_LOADED.set_search_offset((5, 5))
|
|
|
|
|
TREASURES_LIGHTWARD_LOCKED.set_search_offset((5, 5))
|
2023-12-27 12:41:57 +00:00
|
|
|
|
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):
|
2024-02-06 07:58:34 +00:00
|
|
|
|
logger.info('Treasures lightward loaded (event unlocked)')
|
|
|
|
|
return True
|
|
|
|
|
if self.appear(TREASURES_LIGHTWARD_LOCKED):
|
|
|
|
|
logger.info('Treasures lightward loaded (event locked)')
|
2023-12-27 12:41:57 +00:00
|
|
|
|
return True
|
|
|
|
|
|
2024-02-06 21:52:57 +00:00
|
|
|
|
def _dungeon_wait_until_dungeon_list_loaded(self, skip_first_screenshot=True):
|
|
|
|
|
timeout = Timer(1, count=3).start()
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
|
|
|
|
|
# End
|
|
|
|
|
if timeout.reached():
|
|
|
|
|
logger.warning('Wait until dungeon list loaded timeout')
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# Check if having any content
|
|
|
|
|
# List background: 254, guild border: 225
|
|
|
|
|
r, g, b = cv2.split(self.image_crop(LIST_LOADED_CHECK))
|
|
|
|
|
minimum = cv2.min(cv2.min(r, g), b)
|
|
|
|
|
minimum = inrange(minimum, lower=0, upper=180)
|
|
|
|
|
if minimum.size > 100:
|
|
|
|
|
logger.info('Dungeon list loaded')
|
|
|
|
|
break
|
|
|
|
|
|
2023-12-27 05:09:44 +00:00
|
|
|
|
def _dungeon_wait_until_echo_or_war_stabled(self, skip_first_screenshot=True):
|
2023-07-06 14:41:16 +00:00
|
|
|
|
"""
|
|
|
|
|
Returns:
|
|
|
|
|
bool: True if wait success, False if wait timeout.
|
|
|
|
|
|
|
|
|
|
Pages:
|
|
|
|
|
in: page_guide, Survival_Index
|
|
|
|
|
"""
|
|
|
|
|
# Wait until Forgotten_Hall stabled
|
|
|
|
|
timeout = Timer(2, count=4).start()
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
|
|
|
|
|
# End
|
|
|
|
|
if timeout.reached():
|
2023-12-27 05:09:44 +00:00
|
|
|
|
logger.warning('Wait until Echo_of_War stabled timeout')
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
DUNGEON_NAV_LIST.load_rows(main=self)
|
|
|
|
|
|
|
|
|
|
# End
|
2023-12-27 05:09:44 +00:00
|
|
|
|
button = DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Echo_of_War, show_warning=False)
|
2023-07-06 14:41:16 +00:00
|
|
|
|
if button:
|
|
|
|
|
# 513 is the top of the last row of DungeonNav
|
|
|
|
|
if button.area[1] > 513:
|
2023-12-27 05:09:44 +00:00
|
|
|
|
logger.info('DungeonNav row Echo_of_War stabled')
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return True
|
2023-09-22 17:32:09 +00:00
|
|
|
|
else:
|
2023-12-27 05:09:44 +00:00
|
|
|
|
logger.info('No Echo_of_War in list skip waiting')
|
2023-09-22 17:32:09 +00:00
|
|
|
|
return False
|
2023-07-06 14:41:16 +00:00
|
|
|
|
|
2024-02-12 15:29:21 +00:00
|
|
|
|
def _dungeon_nav_goto(self, nav: DungeonNav, skip_first_screenshot=True):
|
2023-07-06 14:41:16 +00:00
|
|
|
|
"""
|
|
|
|
|
Equivalent to `DUNGEON_NAV_LIST.select_row(dungeon.dungeon_nav, main=self)`
|
|
|
|
|
but with tricks to be faster
|
2023-07-06 18:22:20 +00:00
|
|
|
|
|
|
|
|
|
Args:
|
2024-02-12 15:29:21 +00:00
|
|
|
|
nav:
|
2023-07-06 18:22:20 +00:00
|
|
|
|
skip_first_screenshot:
|
2023-07-06 14:41:16 +00:00
|
|
|
|
"""
|
2023-07-06 18:22:20 +00:00
|
|
|
|
logger.hr('Dungeon nav goto', level=2)
|
2024-02-12 15:29:21 +00:00
|
|
|
|
logger.info(f'Dungeon nav goto {nav}')
|
2023-07-06 18:22:20 +00:00
|
|
|
|
|
|
|
|
|
# Wait rows
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
DUNGEON_NAV_LIST.load_rows(main=self)
|
|
|
|
|
if DUNGEON_NAV_LIST.cur_buttons:
|
|
|
|
|
break
|
|
|
|
|
|
2023-09-17 01:34:17 +00:00
|
|
|
|
# Wait first row selected
|
|
|
|
|
timeout = Timer(0.5, count=2).start()
|
|
|
|
|
skip_first_screenshot = True
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
if timeout.reached():
|
|
|
|
|
logger.info('DUNGEON_NAV_LIST not selected')
|
|
|
|
|
break
|
|
|
|
|
if button := DUNGEON_NAV_LIST.get_selected_row(main=self):
|
|
|
|
|
logger.info(f'DUNGEON_NAV_LIST selected at {button}')
|
|
|
|
|
break
|
|
|
|
|
|
2023-07-10 14:20:35 +00:00
|
|
|
|
# Check if it's at the first page.
|
2023-09-17 01:34:17 +00:00
|
|
|
|
if button := DUNGEON_NAV_LIST.keyword2button(KEYWORDS_DUNGEON_NAV.Simulated_Universe, show_warning=False):
|
2023-07-10 14:20:35 +00:00
|
|
|
|
# Going to use a faster method to navigate but can only start from list top
|
|
|
|
|
logger.info('DUNGEON_NAV_LIST at top')
|
2023-09-17 01:34:17 +00:00
|
|
|
|
# Update points if possible
|
|
|
|
|
if DUNGEON_NAV_LIST.is_row_selected(button, main=self):
|
2023-11-01 19:56:01 +00:00
|
|
|
|
self.dungeon_update_simuni()
|
2023-12-27 12:41:57 +00:00
|
|
|
|
# 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')
|
2023-07-10 14:20:35 +00:00
|
|
|
|
else:
|
|
|
|
|
# To start from any list states.
|
|
|
|
|
logger.info('DUNGEON_NAV_LIST not at top')
|
2024-02-12 15:29:21 +00:00
|
|
|
|
DUNGEON_NAV_LIST.select_row(nav, main=self)
|
2023-07-10 14:20:35 +00:00
|
|
|
|
return True
|
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
|
# Check the first page
|
2024-02-12 15:29:21 +00:00
|
|
|
|
if nav in [
|
2023-07-06 14:41:16 +00:00
|
|
|
|
KEYWORDS_DUNGEON_NAV.Simulated_Universe,
|
|
|
|
|
KEYWORDS_DUNGEON_NAV.Calyx_Golden,
|
|
|
|
|
KEYWORDS_DUNGEON_NAV.Calyx_Crimson,
|
|
|
|
|
KEYWORDS_DUNGEON_NAV.Stagnant_Shadow,
|
|
|
|
|
KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion,
|
2023-12-27 12:41:57 +00:00
|
|
|
|
KEYWORDS_DUNGEON_NAV.Forgotten_Hall,
|
|
|
|
|
KEYWORDS_DUNGEON_NAV.Pure_Fiction,
|
2023-07-06 14:41:16 +00:00
|
|
|
|
]:
|
2024-02-12 15:29:21 +00:00
|
|
|
|
button = DUNGEON_NAV_LIST.keyword2button(nav)
|
2023-07-06 14:41:16 +00:00
|
|
|
|
if button:
|
2024-02-12 15:29:21 +00:00
|
|
|
|
DUNGEON_NAV_LIST.select_row(nav, main=self, insight=False)
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# Check the second page
|
|
|
|
|
while 1:
|
|
|
|
|
DUNGEON_NAV_LIST.drag_page('down', main=self)
|
|
|
|
|
# No skip_first_screenshot since drag_page is just called
|
2023-12-27 05:09:44 +00:00
|
|
|
|
if self._dungeon_wait_until_echo_or_war_stabled(skip_first_screenshot=False):
|
2024-02-12 15:29:21 +00:00
|
|
|
|
DUNGEON_NAV_LIST.select_row(nav, main=self, insight=False)
|
2023-07-06 14:41:16 +00:00
|
|
|
|
return True
|
2023-06-14 16:15:14 +00:00
|
|
|
|
|
2024-02-06 21:24:46 +00:00
|
|
|
|
def _dungeon_world_set(self, dungeon: DungeonList, skip_first_screenshot=True):
|
|
|
|
|
"""
|
|
|
|
|
Switch worlds in Calyx_Golden
|
2024-02-09 20:53:01 +00:00
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
bool: True if success to set
|
2024-02-06 21:24:46 +00:00
|
|
|
|
"""
|
|
|
|
|
logger.hr('Dungeon world set', level=2)
|
|
|
|
|
if not dungeon.is_Calyx_Golden:
|
|
|
|
|
logger.warning(f'Dungeon {dungeon} is not Calyx Golden, no need to set world')
|
2024-02-09 20:53:01 +00:00
|
|
|
|
return False
|
2024-02-06 21:24:46 +00:00
|
|
|
|
if dungeon.world is None:
|
|
|
|
|
logger.error(f'Dungeon {dungeon} does not belongs to any world')
|
2024-02-09 20:53:01 +00:00
|
|
|
|
return False
|
2024-02-06 21:24:46 +00:00
|
|
|
|
dic_world_button = {
|
|
|
|
|
KEYWORDS_MAP_WORLD.Jarilo_VI: CALYX_WORLD_1,
|
|
|
|
|
KEYWORDS_MAP_WORLD.The_Xianzhou_Luofu: CALYX_WORLD_2,
|
|
|
|
|
KEYWORDS_MAP_WORLD.Penacony: CALYX_WORLD_3,
|
|
|
|
|
}
|
|
|
|
|
button = dic_world_button.get(dungeon.world)
|
|
|
|
|
if button is None:
|
|
|
|
|
logger.error(f'Dungeon {dungeon} with world {dungeon.world} has no corresponding world button')
|
2024-02-09 20:53:01 +00:00
|
|
|
|
return False
|
2024-02-06 21:24:46 +00:00
|
|
|
|
|
|
|
|
|
logger.info(f'Dungeon world set {dungeon.world}')
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
|
|
|
|
|
# End
|
|
|
|
|
if self.image_color_count(button, color=(18, 18, 18), threshold=180, count=50):
|
|
|
|
|
logger.info(f'Dungeon world at {dungeon.world}')
|
2024-02-09 20:53:01 +00:00
|
|
|
|
return True
|
2024-02-06 21:24:46 +00:00
|
|
|
|
# Click
|
|
|
|
|
if self.ui_page_appear(page_guide, interval=2):
|
|
|
|
|
self.device.click(button)
|
|
|
|
|
continue
|
|
|
|
|
|
2024-02-09 20:53:01 +00:00
|
|
|
|
def _dungeon_world_set_wrapper(self, dungeon: DungeonList, skip_first_screenshot=True):
|
|
|
|
|
"""
|
|
|
|
|
Switch worlds in Calyx_Golden with error handling
|
|
|
|
|
If world tab is not unlocked, fallback to Jarilo dungeons
|
|
|
|
|
"""
|
2024-02-19 10:11:57 +00:00
|
|
|
|
# Wait world tab
|
2024-02-09 20:53:01 +00:00
|
|
|
|
button = CALYX_WORLD_1
|
|
|
|
|
tab = False
|
2024-02-19 10:11:57 +00:00
|
|
|
|
timeout = Timer(0.6, count=3).start()
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
# End
|
|
|
|
|
if timeout.reached():
|
|
|
|
|
break
|
|
|
|
|
# Selected tab
|
|
|
|
|
if self.image_color_count(button, color=(18, 18, 18), threshold=180, count=50):
|
|
|
|
|
tab = True
|
|
|
|
|
break
|
|
|
|
|
# Unselected tab
|
|
|
|
|
if self.image_color_count(button, color=(134, 134, 134), threshold=180, count=50):
|
|
|
|
|
tab = True
|
|
|
|
|
break
|
2024-02-09 20:53:01 +00:00
|
|
|
|
|
2024-02-19 10:11:57 +00:00
|
|
|
|
logger.attr('WorldTab', tab)
|
2024-02-09 20:53:01 +00:00
|
|
|
|
if not tab:
|
|
|
|
|
logger.warning('World tab is not unlocked, fallback to Jarilo dungeons')
|
|
|
|
|
if dungeon.is_Calyx_Golden_Memories:
|
|
|
|
|
dungeon = KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures_Jarilo_VI
|
|
|
|
|
if dungeon.is_Calyx_Golden_Aether:
|
|
|
|
|
dungeon = KEYWORDS_DUNGEON_LIST.Calyx_Golden_Aether_Jarilo_VI
|
|
|
|
|
if dungeon.is_Calyx_Golden_Treasures:
|
|
|
|
|
dungeon = KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures_Jarilo_VI
|
|
|
|
|
|
2024-02-19 10:11:57 +00:00
|
|
|
|
self._dungeon_world_set(dungeon, skip_first_screenshot=skip_first_screenshot)
|
|
|
|
|
return dungeon
|
2024-02-09 20:53:01 +00:00
|
|
|
|
|
2023-06-14 16:15:14 +00:00
|
|
|
|
def _dungeon_insight(self, dungeon: DungeonList):
|
|
|
|
|
"""
|
|
|
|
|
Pages:
|
|
|
|
|
in: page_guide, Survival_Index, nav including dungeon
|
|
|
|
|
out: page_guide, Survival_Index, nav including dungeon, dungeon insight
|
|
|
|
|
"""
|
|
|
|
|
logger.hr('Dungeon insight', level=2)
|
2024-02-07 04:41:53 +00:00
|
|
|
|
DUNGEON_LIST.use_plane = bool(dungeon.is_Calyx_Crimson)
|
2023-06-14 16:15:14 +00:00
|
|
|
|
# Insight dungeon
|
|
|
|
|
DUNGEON_LIST.insight_row(dungeon, main=self)
|
|
|
|
|
# Check if dungeon unlocked
|
2023-06-20 02:55:32 +00:00
|
|
|
|
for entrance in DUNGEON_LIST.navigates:
|
2023-06-14 16:15:14 +00:00
|
|
|
|
entrance: OcrResultButton = entrance
|
|
|
|
|
logger.warning(f'Teleport {entrance.matched_keyword} is not unlocked')
|
|
|
|
|
if entrance == dungeon:
|
|
|
|
|
logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked')
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# Find teleport button
|
2023-06-20 02:55:32 +00:00
|
|
|
|
if dungeon not in [tp.matched_keyword for tp in DUNGEON_LIST.teleports]:
|
2023-06-14 16:15:14 +00:00
|
|
|
|
# Dungeon name is insight but teleport button is not
|
|
|
|
|
logger.info('Dungeon name is insight, swipe down a little bit to find the teleport button')
|
2023-06-29 04:56:05 +00:00
|
|
|
|
if dungeon.is_Forgotten_Hall:
|
|
|
|
|
DUNGEON_LIST.drag_vector = (-0.4, -0.2) # Keyword loaded is reversed
|
|
|
|
|
else:
|
|
|
|
|
DUNGEON_LIST.drag_vector = (0.2, 0.4)
|
2024-02-18 17:43:05 +00:00
|
|
|
|
DUNGEON_LIST.limit_entrance = True
|
2023-06-14 16:15:14 +00:00
|
|
|
|
DUNGEON_LIST.insight_row(dungeon, main=self)
|
|
|
|
|
DUNGEON_LIST.drag_vector = DraggableList.drag_vector
|
2024-02-18 17:43:05 +00:00
|
|
|
|
DUNGEON_LIST.limit_entrance = False
|
2023-06-14 16:15:14 +00:00
|
|
|
|
DUNGEON_LIST.load_rows(main=self)
|
|
|
|
|
# Check if dungeon unlocked
|
2023-06-20 02:55:32 +00:00
|
|
|
|
for entrance in DUNGEON_LIST.navigates:
|
2023-06-14 16:15:14 +00:00
|
|
|
|
if entrance == dungeon:
|
|
|
|
|
logger.error(f'Trying to enter dungeon {dungeon}, but teleport is not unlocked')
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2023-06-29 14:28:08 +00:00
|
|
|
|
def _dungeon_enter(self, dungeon, enter_check_button=COMBAT_PREPARE, skip_first_screenshot=True):
|
2023-06-14 16:15:14 +00:00
|
|
|
|
"""
|
|
|
|
|
Pages:
|
|
|
|
|
in: page_guide, Survival_Index, nav including dungeon
|
2023-06-29 04:56:05 +00:00
|
|
|
|
out: COMBAT_PREPARE, FORGOTTEN_HALL_CHECK
|
2023-06-14 16:15:14 +00:00
|
|
|
|
"""
|
|
|
|
|
logger.hr('Dungeon enter', level=2)
|
2024-02-07 04:41:53 +00:00
|
|
|
|
DUNGEON_LIST.use_plane = bool(dungeon.is_Calyx_Crimson)
|
2023-06-14 16:15:14 +00:00
|
|
|
|
skip_first_load = True
|
|
|
|
|
while 1:
|
|
|
|
|
if skip_first_screenshot:
|
|
|
|
|
skip_first_screenshot = False
|
|
|
|
|
else:
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
|
|
|
|
|
# End
|
2023-06-29 14:28:08 +00:00
|
|
|
|
if self.appear(enter_check_button):
|
|
|
|
|
logger.info(f'Arrive {enter_check_button.name}')
|
2023-06-14 16:15:14 +00:00
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# Additional
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# Click teleport
|
|
|
|
|
if self.appear(page_guide.check_button, interval=1):
|
|
|
|
|
if skip_first_load:
|
|
|
|
|
skip_first_load = False
|
|
|
|
|
else:
|
|
|
|
|
DUNGEON_LIST.load_rows(main=self)
|
|
|
|
|
entrance = DUNGEON_LIST.keyword2button(dungeon)
|
|
|
|
|
if entrance is not None:
|
|
|
|
|
self.device.click(entrance)
|
|
|
|
|
self.interval_reset(page_guide.check_button)
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
logger.warning(f'Cannot find dungeon entrance of {dungeon}')
|
|
|
|
|
continue
|
|
|
|
|
|
2023-11-02 10:56:20 +00:00
|
|
|
|
def get_dungeon_interact(self) -> DungeonList | None:
|
|
|
|
|
"""
|
|
|
|
|
Pages:
|
|
|
|
|
in: page_main
|
|
|
|
|
"""
|
|
|
|
|
if not self.appear(DUNGEON_COMBAT_INTERACT):
|
|
|
|
|
logger.info('No dungeon interact')
|
|
|
|
|
return None
|
|
|
|
|
|
2024-05-08 13:46:53 +00:00
|
|
|
|
self.acquire_lang_checked()
|
|
|
|
|
|
2023-11-02 10:56:20 +00:00
|
|
|
|
ocr = OcrDungeonList(DUNGEON_COMBAT_INTERACT_TEXT)
|
|
|
|
|
result = ocr.detect_and_ocr(self.device.image)
|
|
|
|
|
|
2024-05-08 13:46:53 +00:00
|
|
|
|
dungeon = None
|
|
|
|
|
# Special match names in English
|
|
|
|
|
# Second row must have at least 3 characters which is the shortest name "Ire"
|
|
|
|
|
# Stangnant Shadow: Shape of
|
|
|
|
|
# Quanta
|
|
|
|
|
if len(result) == 2 and len(result[1].ocr_text) >= 3:
|
|
|
|
|
first, second = result[0].ocr_text, result[1].ocr_text
|
|
|
|
|
if re.search(r'Stagnant\s*Shadow', first):
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Stagnant_Shadow=True)
|
|
|
|
|
elif re.search(r'Cavern\s*of\s*Corrosion', first):
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Cavern_of_Corrosion=True)
|
|
|
|
|
elif re.search(r'Echo\s*of\s*War', first):
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Echo_of_War=True)
|
|
|
|
|
elif re.search(r'Calyx[\s(]+Golden', first):
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Golden=True, world=self.plane.world)
|
|
|
|
|
elif re.search(r'Calyx[\s(]+Crimson', first):
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Crimson=True, plane=self.plane)
|
|
|
|
|
if dungeon is not None:
|
|
|
|
|
logger.attr('DungeonInteract', dungeon)
|
|
|
|
|
return dungeon
|
|
|
|
|
|
|
|
|
|
# Join
|
2023-11-02 10:56:20 +00:00
|
|
|
|
result = ' '.join([row.ocr_text for row in result])
|
|
|
|
|
|
2024-05-08 13:46:53 +00:00
|
|
|
|
# Special match names in Chinese
|
|
|
|
|
# Only calyxes need spacial match
|
|
|
|
|
if res := re.search(r'(^.+之蕾)', result):
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Crimson=True, plane=self.plane)
|
|
|
|
|
if dungeon is not None:
|
|
|
|
|
logger.attr('DungeonInteract', dungeon)
|
|
|
|
|
return dungeon
|
|
|
|
|
dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Golden=True, world=self.plane.world)
|
|
|
|
|
if dungeon is not None:
|
|
|
|
|
logger.attr('DungeonInteract', dungeon)
|
|
|
|
|
return dungeon
|
2023-11-02 10:56:20 +00:00
|
|
|
|
|
|
|
|
|
# Dungeons
|
|
|
|
|
try:
|
|
|
|
|
dungeon = DungeonList.find(result)
|
|
|
|
|
logger.attr('DungeonInteract', dungeon)
|
|
|
|
|
return dungeon
|
|
|
|
|
except ScriptError:
|
|
|
|
|
pass
|
|
|
|
|
# Simulated Universe returns Simulated_Universe_World_1
|
|
|
|
|
try:
|
|
|
|
|
dungeon = DungeonNav.find(result)
|
|
|
|
|
if dungeon == KEYWORDS_DUNGEON_NAV.Simulated_Universe:
|
|
|
|
|
dungeon = KEYWORDS_DUNGEON_LIST.Simulated_Universe_World_1
|
|
|
|
|
logger.attr('DungeonInteract', dungeon)
|
|
|
|
|
return dungeon
|
|
|
|
|
except ScriptError:
|
|
|
|
|
pass
|
|
|
|
|
# Unknown
|
|
|
|
|
logger.attr('DungeonInteract', None)
|
|
|
|
|
return None
|
|
|
|
|
|
2023-12-08 15:07:28 +00:00
|
|
|
|
def dungeon_goto_rogue(self):
|
|
|
|
|
"""
|
|
|
|
|
Goto Simulated Universe page but not pressing the TELEPORT button
|
|
|
|
|
|
|
|
|
|
Pages:
|
|
|
|
|
in: Any
|
|
|
|
|
out: page_guide, Survival_Index, Simulated_Universe
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
self = DungeonUI('src')
|
|
|
|
|
self.device.screenshot()
|
|
|
|
|
self.dungeon_goto_rogue()
|
|
|
|
|
self._rogue_teleport()
|
|
|
|
|
"""
|
|
|
|
|
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
|
|
|
|
if self.appear(SURVIVAL_INDEX_LOADED):
|
|
|
|
|
logger.info('Already at nav Simulated_Universe')
|
|
|
|
|
else:
|
2024-02-12 15:29:21 +00:00
|
|
|
|
self._dungeon_nav_goto(KEYWORDS_DUNGEON_NAV.Simulated_Universe)
|
2023-12-08 15:07:28 +00:00
|
|
|
|
|
2023-06-14 16:15:14 +00:00
|
|
|
|
def dungeon_goto(self, dungeon: DungeonList):
|
|
|
|
|
"""
|
|
|
|
|
Returns:
|
|
|
|
|
bool: If success
|
|
|
|
|
|
|
|
|
|
Pages:
|
2023-07-10 14:20:35 +00:00
|
|
|
|
in: page_guide, Survival_Index
|
2023-06-14 16:15:14 +00:00
|
|
|
|
out: COMBAT_PREPARE if success
|
|
|
|
|
page_guide if failed
|
|
|
|
|
|
|
|
|
|
Examples:
|
2023-07-10 14:20:35 +00:00
|
|
|
|
from tasks.dungeon.keywords import KEYWORDS_DUNGEON_LIST
|
2023-10-16 11:13:13 +00:00
|
|
|
|
self = DungeonUI('src')
|
2023-06-14 16:15:14 +00:00
|
|
|
|
self.device.screenshot()
|
2023-07-10 14:20:35 +00:00
|
|
|
|
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
|
2023-06-14 16:15:14 +00:00
|
|
|
|
self.dungeon_goto(KEYWORDS_DUNGEON_LIST.Calyx_Crimson_Harmony)
|
|
|
|
|
"""
|
|
|
|
|
# Reset search button
|
|
|
|
|
DUNGEON_LIST.search_button = OCR_DUNGEON_LIST
|
|
|
|
|
|
2024-02-06 21:24:46 +00:00
|
|
|
|
if dungeon.is_Calyx_Crimson \
|
2023-07-06 14:41:16 +00:00
|
|
|
|
or dungeon.is_Stagnant_Shadow \
|
2023-09-26 19:14:12 +00:00
|
|
|
|
or dungeon.is_Cavern_of_Corrosion \
|
|
|
|
|
or dungeon.is_Echo_of_War:
|
2024-02-12 15:29:21 +00:00
|
|
|
|
self._dungeon_nav_goto(dungeon.dungeon_nav)
|
2024-02-06 21:52:57 +00:00
|
|
|
|
self._dungeon_wait_until_dungeon_list_loaded()
|
2023-06-27 15:52:41 +00:00
|
|
|
|
self._dungeon_insight(dungeon)
|
|
|
|
|
self._dungeon_enter(dungeon)
|
|
|
|
|
return True
|
2024-02-06 21:24:46 +00:00
|
|
|
|
if dungeon.is_Calyx_Golden:
|
2024-02-12 15:29:21 +00:00
|
|
|
|
self._dungeon_nav_goto(dungeon.dungeon_nav)
|
2024-02-06 21:52:57 +00:00
|
|
|
|
self._dungeon_wait_until_dungeon_list_loaded()
|
2024-02-19 10:11:57 +00:00
|
|
|
|
dungeon = self._dungeon_world_set_wrapper(dungeon)
|
2024-02-06 21:52:57 +00:00
|
|
|
|
self._dungeon_wait_until_dungeon_list_loaded()
|
2024-02-06 21:24:46 +00:00
|
|
|
|
self._dungeon_insight(dungeon)
|
|
|
|
|
self._dungeon_enter(dungeon)
|
|
|
|
|
return True
|
2023-06-14 16:15:14 +00:00
|
|
|
|
|
|
|
|
|
logger.error(f'Goto dungeon {dungeon} is not supported')
|
|
|
|
|
return False
|