feat(task): 支持处理外出行动 & 优化部分流程

1. 新增支持培育行动页面的外出
2. 优化练习结束流程
3. 优化未读交流检测逻辑
This commit is contained in:
XcantloadX 2025-02-25 20:52:29 +08:00
parent 133f084c19
commit 03fdfaa221
9 changed files with 84 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 KiB

View File

@ -0,0 +1 @@
{"definitions":{"8ded6c98-85ea-4858-a66d-4fc8caecb7c5":{"name":"InPurodyuusu.ButtonIconOuting","displayName":"行动按钮图标 外出(おでかけ)","type":"template","annotationId":"8ded6c98-85ea-4858-a66d-4fc8caecb7c5","useHintRect":false}},"annotations":[{"id":"8ded6c98-85ea-4858-a66d-4fc8caecb7c5","type":"rect","data":{"x1":233,"y1":962,"x2":316,"y2":1037}}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

View File

@ -0,0 +1 @@
{"definitions":{"ee4e512b-4982-49b6-9c71-31984b58e1d0":{"name":"InPurodyuusu.TitleIconOuting","displayName":"外出(おでかけ)页面 标题图标","type":"template","annotationId":"ee4e512b-4982-49b6-9c71-31984b58e1d0","useHintRect":false}},"annotations":[{"id":"ee4e512b-4982-49b6-9c71-31984b58e1d0","type":"rect","data":{"x1":77,"y1":78,"x2":147,"y2":139}}]}

View File

@ -46,11 +46,11 @@ def handle_unread_commu(img: MatLike | None = None) -> bool:
return any(color.raw().in_range(c, RANGE) for c in colors)
# 防止截图速度过快时,截图到了未加载完全的画面
cd = Interval()
cd = Interval(seconds=0.6)
hit = 0
HIT_THRESHOLD = 2
while True:
if not is_fastforwarding():
if image.find(R.Common.ButtonCommuFastforward) and not is_fastforwarding():
logger.debug("Unread commu hit %d/%d", hit, HIT_THRESHOLD)
hit += 1
else:

View File

@ -21,8 +21,10 @@ from kotonebot.backend.util import AdaptiveWait, Countdown, crop, cropped
from kotonebot.backend.dispatch import DispatcherContext, SimpleDispatcher
from kotonebot import ocr, device, contains, image, regex, action, sleep, color, Rect, wait
from .non_lesson_actions import (
enter_allowance, allowance_available, study_available, enter_study,
is_rest_available, rest
enter_allowance, allowance_available,
study_available, enter_study,
is_rest_available, rest,
outing_available, enter_outing
)
class SkillCard(NamedTuple):
@ -480,6 +482,8 @@ def practice():
(SimpleDispatcher('practice.end')
.click(contains("上昇"), finish=True, log="Click to finish 上昇")
.until(contains("審査基準"))
# 弹出 P 饮料溢出对话框时,背景模糊,导致上面两个都检测不到
.until(R.InPurodyuusu.TextPDrinkMax)
.click('center')
).run()
@ -727,7 +731,9 @@ def week_normal(week_first: bool = False):
pass
# 没有推荐行动
elif executed_action is None:
if allowance_available():
if outing_available():
enter_outing()
elif allowance_available():
enter_allowance()
elif study_available():
enter_study()

View File

@ -1,19 +1,17 @@
"""
此文件包含非练习的行动
此文件包含非练习/考试的行动
具体包括おでかけ相談活動支給授業
"""
from logging import getLogger
from kotonebot.backend.dispatch import SimpleDispatcher
from kotonebot.backend.util import Interval
from .. import R
from ..game_ui import CommuEventButtonUI, EventButton
from .common import acquisitions, AcquisitionType
from kotonebot import device, image, ocr, debug, action, sleep
from .common import acquisitions
from ..game_ui import CommuEventButtonUI
from kotonebot.backend.util import Interval
from kotonebot.errors import UnrecoverableError
from ..actions.loading import wait_loading_end, wait_loading_start
from kotonebot import device, image, action, sleep
from kotonebot.backend.dispatch import SimpleDispatcher
logger = getLogger(__name__)
@ -123,6 +121,13 @@ def rest():
.click(R.InPurodyuusu.RestConfirmBtn, finish=True)
).run()
@action('判断是否处于行动页面')
def at_action_scene():
return image.find_multi([
R.InPurodyuusu.TextPDiary, # 普通周
R.InPurodyuusu.ButtonFinalPracticeDance # 离考试剩余一周
]) is not None
if __name__ == '__main__':
from kotonebot.backend.context import manual_context, init_context
init_context()
@ -146,3 +151,55 @@ if __name__ == '__main__':
while acquisitions() is None:
logger.info("Waiting for acquisitions finished.")
logger.info("授業 completed.")
@action('判断是否可以外出')
def outing_available():
"""
判断是否可以外出おでかけ
"""
return image.find(R.InPurodyuusu.ButtonIconOuting) is not None
@action('执行外出')
def enter_outing():
"""
执行外出おでかけ
前置条件位于行动页面且所有行动按钮清晰可见 \n
结束状态位于行动页面
"""
logger.info("Executing おでかけ.")
# 点击外出
logger.info("Double clicking on おでかけ.")
device.double_click(image.expect(R.InPurodyuusu.ButtonIconOuting))
# 等待进入页面
while not image.find(R.InPurodyuusu.TitleIconOuting):
logger.debug("Waiting for おでかけ screen.")
acquisitions()
# 固定选中第二个选项
# TODO: 可能需要二次处理外出事件
# [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_outing.png]
ui = CommuEventButtonUI()
buttons = ui.all()
if not buttons:
raise UnrecoverableError("Failed to find any buttons.")
target_btn = buttons[1]
logger.debug('Clicking "%s".', target_btn.description)
if target_btn.selected:
device.click(target_btn)
else:
device.double_click(target_btn)
it = Interval()
while True:
device.screenshot()
if at_action_scene():
break
elif acquisitions():
pass
# [screenshots\produce\outing_ap_confirm.png]
elif image.find(R.Common.ButtonSelect):
logger.info("AP max out dialog found. Click to continue.")
device.click()
sleep(0.1)
it.wait()
logger.info("おでかけ completed.")

View File

@ -107,7 +107,13 @@ class EventButton:
# 参考图片:
# [screenshots/produce/action_study3.png]
# TODO: CommuEventButtonUI 需要能够识别不可用的按钮
class CommuEventButtonUI:
"""
此类用于识别培育中交流中出现的事件/效果里的按钮
例如外出おでかけ冲刺周课程选择这两个页面的选择按钮
"""
def __init__(
self,
selected_colors: list[tuple[HsvColor, HsvColor]] = DEFAULT_COLORS,

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB