Add: Use techniques (#36)

* Add: Use techniques

* Add: Use technique to daily quests task

* Upd: change to use control module

* Upd: handle dungeon popup

* Upd: Make UseTechniqueUI extends from MapControlJoystick & ForgottenUI

* Upd: move _enter_forgotten_hall_dungeon() to ForgottenHallUI; extract choose first character method
This commit is contained in:
Hengyu 2023-07-06 00:15:16 +08:00 committed by GitHub
parent 862a0b7453
commit e9a02da75b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 183 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -9,6 +9,7 @@ from tasks.daily.camera import CameraUI
from tasks.daily.consumable_usage import ConsumableUsageUI from tasks.daily.consumable_usage import ConsumableUsageUI
from tasks.daily.keywords import DailyQuest, DailyQuestState, KEYWORDS_DAILY_QUEST, KEYWORDS_DAILY_QUEST_STATE from tasks.daily.keywords import DailyQuest, DailyQuestState, KEYWORDS_DAILY_QUEST, KEYWORDS_DAILY_QUEST_STATE
from tasks.daily.synthesize import SynthesizeConsumablesUI, SynthesizeMaterialUI from tasks.daily.synthesize import SynthesizeConsumablesUI, SynthesizeMaterialUI
from tasks.daily.use_technique import UseTechniqueUI
from tasks.dungeon.keywords import KEYWORDS_DUNGEON_TAB from tasks.dungeon.keywords import KEYWORDS_DUNGEON_TAB
from tasks.dungeon.ui import DungeonUI from tasks.dungeon.ui import DungeonUI
@ -186,6 +187,9 @@ class DailyQuestUI(DungeonUI):
if KEYWORDS_DAILY_QUEST.Use_Consumables_1_time in quests: if KEYWORDS_DAILY_QUEST.Use_Consumables_1_time in quests:
if ConsumableUsageUI(self.config, self.device).use_consumable(): if ConsumableUsageUI(self.config, self.device).use_consumable():
done += 1 done += 1
if KEYWORDS_DAILY_QUEST.Use_Technique_2_times in quests:
UseTechniqueUI(self.config, self.device).use_technique(2)
done += 1
return done return done

View File

@ -0,0 +1,51 @@
from module.logger import logger
from tasks.base.page import page_main
from tasks.dungeon.keywords import KEYWORDS_DUNGEON_LIST
from tasks.forgotten_hall.keywords import KEYWORDS_FORGOTTEN_HALL_STAGE
from tasks.forgotten_hall.ui import ForgottenHallUI
from tasks.map.control.joystick import MapControlJoystick
class UseTechniqueUI(MapControlJoystick, ForgottenHallUI):
def _use_technique(self, count: int, skip_first_screenshot=True):
remains = self.map_get_technique_points()
if count > remains:
logger.warning(f"Try to use technique {count} times but only have {remains}")
return
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
remains_after = self.map_get_technique_points()
if remains - remains_after >= count:
logger.info(f"{remains - remains_after} techniques used")
break
self.handle_map_E()
def use_technique(self, count: int, skip_first_screenshot=True):
"""
Args:
skip_first_screenshot:
count: use {count} times
Examples:
self = UseTechniquesUI('alas')
self.device.screenshot()
self.use_techniques(2)
Pages:
in: Any
out: page_forgotten_hall, FORGOTTEN_HALL_CHECKED
"""
logger.hr('Use techniques', level=2)
self.ui_ensure(page_main)
self.stage_goto(KEYWORDS_DUNGEON_LIST.The_Last_Vestiges_of_Towering_Citadel,
KEYWORDS_FORGOTTEN_HALL_STAGE.Stage_1)
self._choose_first_character()
self._enter_forgotten_hall_dungeon()
self._use_technique(count, skip_first_screenshot=skip_first_screenshot)
self.exit_dungeon()
self.ui_goto_main()

View File

@ -3,6 +3,36 @@ 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 ```
DUNGEON_ENTER_CHECKED = ButtonWrapper(
name='DUNGEON_ENTER_CHECKED',
share=Button(
file='./assets/share/forgotten_hall/DUNGEON_ENTER_CHECKED.png',
area=(26, 247, 40, 256),
search=(6, 227, 60, 276),
color=(175, 180, 183),
button=(26, 247, 40, 256),
),
)
EFFECT_NOTIFICATION = ButtonWrapper(
name='EFFECT_NOTIFICATION',
share=Button(
file='./assets/share/forgotten_hall/EFFECT_NOTIFICATION.png',
area=(237, 302, 315, 380),
search=(217, 282, 335, 400),
color=(128, 114, 85),
button=(237, 302, 315, 380),
),
)
ENTER_FORGOTTEN_HALL_DUNGEON = ButtonWrapper(
name='ENTER_FORGOTTEN_HALL_DUNGEON',
share=Button(
file='./assets/share/forgotten_hall/ENTER_FORGOTTEN_HALL_DUNGEON.png',
area=(1233, 653, 1241, 680),
search=(1213, 633, 1261, 700),
color=(219, 221, 221),
button=(1233, 653, 1241, 680),
),
)
ENTRANCE_CHECKED = ButtonWrapper( ENTRANCE_CHECKED = ButtonWrapper(
name='ENTRANCE_CHECKED', name='ENTRANCE_CHECKED',
share=Button( share=Button(
@ -13,6 +43,36 @@ ENTRANCE_CHECKED = ButtonWrapper(
button=(62, 662, 80, 680), button=(62, 662, 80, 680),
), ),
) )
EXIT_CONFIRM = ButtonWrapper(
name='EXIT_CONFIRM',
share=Button(
file='./assets/share/forgotten_hall/EXIT_CONFIRM.png',
area=(776, 458, 800, 482),
search=(756, 438, 820, 502),
color=(94, 88, 76),
button=(776, 458, 800, 482),
),
)
EXIT_DUNGEON = ButtonWrapper(
name='EXIT_DUNGEON',
share=Button(
file='./assets/share/forgotten_hall/EXIT_DUNGEON.png',
area=(15, 45, 45, 75),
search=(0, 25, 65, 95),
color=(113, 117, 124),
button=(15, 45, 45, 75),
),
)
FIRST_CHARACTER = ButtonWrapper(
name='FIRST_CHARACTER',
share=Button(
file='./assets/share/forgotten_hall/FIRST_CHARACTER.png',
area=(54, 100, 150, 212),
search=(34, 80, 170, 232),
color=(145, 125, 103),
button=(54, 100, 150, 212),
),
)
LAST_VERTIGES = ButtonWrapper( LAST_VERTIGES = ButtonWrapper(
name='LAST_VERTIGES', name='LAST_VERTIGES',
share=Button( share=Button(

View File

@ -3,7 +3,8 @@ import numpy as np
from ppocronnx.predict_system import BoxedResult from ppocronnx.predict_system import BoxedResult
from module.base.base import ModuleBase from module.base.base import ModuleBase
from module.base.utils import area_offset, color_similarity_2d, crop from module.base.timer import Timer
from module.base.utils import area_offset, color_similarity_2d, crop, get_color
from module.logger.logger import logger from module.logger.logger import logger
from module.ocr.keyword import Keyword from module.ocr.keyword import Keyword
from module.ocr.ocr import Ocr, OcrResultButton from module.ocr.ocr import Ocr, OcrResultButton
@ -14,6 +15,7 @@ from tasks.dungeon.keywords import DungeonList
from tasks.dungeon.ui import DungeonUI from tasks.dungeon.ui import DungeonUI
from tasks.forgotten_hall.assets.assets_forgotten_hall import * from tasks.forgotten_hall.assets.assets_forgotten_hall import *
from tasks.forgotten_hall.keywords import * from tasks.forgotten_hall.keywords import *
from tasks.map.control.joystick import MapControlJoystick
class ForgottenHallStageOcr(Ocr): class ForgottenHallStageOcr(Ocr):
@ -116,3 +118,68 @@ class ForgottenHallUI(UI):
dungeon_ui = DungeonUI(config=self.config, device=self.device) dungeon_ui = DungeonUI(config=self.config, device=self.device)
dungeon_ui.dungeon_goto(forgotten_hall) dungeon_ui.dungeon_goto(forgotten_hall)
STAGE_LIST.select_row(stage_keyword, main=self) STAGE_LIST.select_row(stage_keyword, main=self)
def exit_dungeon(self, skip_first_screenshot=True):
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(FORGOTTEN_HALL_CHECK):
logger.info("Forgotten hall dungeon exited")
break
if self.appear_then_click(EXIT_DUNGEON):
continue
if self.appear_then_click(EXIT_CONFIRM):
continue
def _choose_first_character(self, skip_first_screenshot=True):
"""
A temporary method used to choose the first character only
"""
interval = Timer(1)
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if np.mean(get_color(self.device.image, ENTER_FORGOTTEN_HALL_DUNGEON.area)) > 128:
logger.info("First character is chosen")
break
if interval.reached():
self.device.click(FIRST_CHARACTER)
interval.reset()
def _enter_forgotten_hall_dungeon(self, skip_first_screenshot=True):
"""
called after team is set
"""
interval = Timer(1)
joystick = MapControlJoystick(self.config, self.device)
while 1: # enter ui -> popup
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(EFFECT_NOTIFICATION):
break
if interval.reached() and np.mean(get_color(self.device.image, ENTER_FORGOTTEN_HALL_DUNGEON.area)) > 128:
self.device.click(ENTER_FORGOTTEN_HALL_DUNGEON)
interval.reset()
skip_first_screenshot = True
while 1: # pop up -> dungeon inside
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.match_template_color(DUNGEON_ENTER_CHECKED):
logger.info("Forgotten hall dungeon entered")
break
joystick.handle_map_run()