diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_goal_clear_next.png.json b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_goal_clear_next.png.json index ef657ad..5346ece 100644 --- a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_goal_clear_next.png.json +++ b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_goal_clear_next.png.json @@ -1 +1 @@ -{"definitions":{"05890a1b-8764-4e9f-9d21-65d292c22e13":{"name":"InPurodyuusu.BoxGoalClearNext","displayName":"培育目标达成 NEXT 文字区域","type":"hint-box","annotationId":"05890a1b-8764-4e9f-9d21-65d292c22e13","useHintRect":false}},"annotations":[{"id":"05890a1b-8764-4e9f-9d21-65d292c22e13","type":"rect","data":{"x1":79,"y1":503,"x2":157,"y2":532}}]} \ No newline at end of file +{"definitions":{"05890a1b-8764-4e9f-9d21-65d292c22e13":{"name":"InPurodyuusu.TextGoalClearNext","displayName":"培育目标达成 NEXT 文字","type":"template","annotationId":"05890a1b-8764-4e9f-9d21-65d292c22e13","useHintRect":false}},"annotations":[{"id":"05890a1b-8764-4e9f-9d21-65d292c22e13","type":"rect","data":{"x1":79,"y1":503,"x2":157,"y2":532}}]} \ No newline at end of file diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_pdrink_max_confirm.png.json b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_pdrink_max_confirm.png.json index 6792900..0af30e6 100644 --- a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_pdrink_max_confirm.png.json +++ b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_pdrink_max_confirm.png.json @@ -1 +1 @@ -{"definitions":{"582d36c0-0916-4706-9833-4fbc026701f5":{"name":"InPurodyuusu.BoxPDrinkMaxConfirmTitle","displayName":"P饮料溢出 不领取弹窗标题","type":"hint-box","annotationId":"582d36c0-0916-4706-9833-4fbc026701f5","useHintRect":false}},"annotations":[{"id":"582d36c0-0916-4706-9833-4fbc026701f5","type":"rect","data":{"x1":46,"y1":829,"x2":270,"y2":876}}]} \ No newline at end of file +{"definitions":{"582d36c0-0916-4706-9833-4fbc026701f5":{"name":"InPurodyuusu.TextPDrinkMaxConfirmTitle","displayName":"P饮料溢出 不领取弹窗标题","type":"template","annotationId":"582d36c0-0916-4706-9833-4fbc026701f5","useHintRect":false}},"annotations":[{"id":"582d36c0-0916-4706-9833-4fbc026701f5","type":"rect","data":{"x1":46,"y1":829,"x2":270,"y2":876}}]} \ No newline at end of file diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink.png b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink.png new file mode 100644 index 0000000..dc6134e Binary files /dev/null and b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink.png differ diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink.png.json b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink.png.json new file mode 100644 index 0000000..7047210 --- /dev/null +++ b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink.png.json @@ -0,0 +1 @@ +{"definitions":{"8c179a21-be6f-4db8-a9b0-9afeb5c36b1c":{"name":"InPurodyuusu.TextPDrink","displayName":"文本「Pドリンク」","type":"template","annotationId":"8c179a21-be6f-4db8-a9b0-9afeb5c36b1c","useHintRect":false,"description":"用于 P 饮料选择对话框"}},"annotations":[{"id":"8c179a21-be6f-4db8-a9b0-9afeb5c36b1c","type":"rect","data":{"x1":244,"y1":615,"x2":357,"y2":641}}]} \ No newline at end of file diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_item.png.json b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_item.png.json index 4f00a96..3cd656a 100644 --- a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_item.png.json +++ b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_item.png.json @@ -1 +1 @@ -{"definitions":{"6b58d90d-2e5e-4b7f-bc01-941f2633de89":{"name":"InPurodyuusu.BoxSelectPStuff","displayName":"选择奖励对话框提示语","type":"hint-box","annotationId":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","useHintRect":false},"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a":{"name":"InPurodyuusu.BoxSelectPStuffComfirm","displayName":"选择奖励对话框 领取按钮","type":"hint-box","annotationId":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","useHintRect":false}},"annotations":[{"id":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","type":"rect","data":{"x1":62,"y1":558,"x2":655,"y2":716}},{"id":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","type":"rect","data":{"x1":256,"y1":1064,"x2":478,"y2":1128}}]} \ No newline at end of file +{"definitions":{"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a":{"name":"InPurodyuusu.BoxSelectPStuffComfirm","displayName":"选择奖励对话框 领取按钮","type":"hint-box","annotationId":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","useHintRect":false},"c948f136-416f-447e-8152-54a1cd1d1329":{"name":"InPurodyuusu.TextClaim","displayName":"文字「受け取る」","type":"template","annotationId":"c948f136-416f-447e-8152-54a1cd1d1329","useHintRect":false,"description":"用于 P 物品、P 饮料、技能卡选择对话框"},"0c0627be-4a09-4450-a078-1858d3ace532":{"name":"InPurodyuusu.TextPItem","displayName":"文字「Pアイテム」","type":"template","annotationId":"0c0627be-4a09-4450-a078-1858d3ace532","useHintRect":false,"description":"用于 P 物品选择对话框"}},"annotations":[{"id":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","type":"rect","data":{"x1":256,"y1":1064,"x2":478,"y2":1128}},{"id":"c948f136-416f-447e-8152-54a1cd1d1329","type":"rect","data":{"x1":144,"y1":608,"x2":245,"y2":647}},{"id":"0c0627be-4a09-4450-a078-1858d3ace532","type":"rect","data":{"x1":247,"y1":613,"x2":354,"y2":645}}]} \ No newline at end of file diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_skill_card.png b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_skill_card.png new file mode 100644 index 0000000..5153fec Binary files /dev/null and b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_skill_card.png differ diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_skill_card.png.json b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_skill_card.png.json new file mode 100644 index 0000000..c446368 --- /dev/null +++ b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_skill_card.png.json @@ -0,0 +1 @@ +{"definitions":{"d271a24f-efe8-424d-8fd5-f6b3756ba4ca":{"name":"InPurodyuusu.TextSkillCard","displayName":"文字「スキルカード」","type":"template","annotationId":"d271a24f-efe8-424d-8fd5-f6b3756ba4ca","useHintRect":false,"description":"用于技能卡选择对话框"}},"annotations":[{"id":"d271a24f-efe8-424d-8fd5-f6b3756ba4ca","type":"rect","data":{"x1":229,"y1":614,"x2":372,"y2":645}}]} \ No newline at end of file diff --git a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_skill_card_enhanced.png.json b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_skill_card_enhanced.png.json index 965b58b..ca4c9c7 100644 --- a/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_skill_card_enhanced.png.json +++ b/kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_skill_card_enhanced.png.json @@ -1 +1 @@ -{"definitions":{"6b58d90d-2e5e-4b7f-bc01-941f2633de89":{"name":"InPurodyuusu.BoxSkillCardEnhaced","displayName":"技能卡强化文本提示","type":"hint-box","annotationId":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","useHintRect":false}},"annotations":[{"id":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","type":"rect","data":{"x1":49,"y1":948,"x2":676,"y2":1106}}]} \ No newline at end of file +{"definitions":{"6b58d90d-2e5e-4b7f-bc01-941f2633de89":{"name":"InPurodyuusu.IconSkillCardEventBubble","displayName":"技能卡事件气泡框图标","type":"template","annotationId":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","useHintRect":false,"description":"背景上左右两边的星星"}},"annotations":[{"id":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","type":"rect","data":{"x1":46,"y1":1007,"x2":79,"y2":1047}}]} \ No newline at end of file diff --git a/kotonebot/tasks/actions/common.py b/kotonebot/tasks/actions/common.py index 8988a37..a4aa068 100644 --- a/kotonebot/tasks/actions/common.py +++ b/kotonebot/tasks/actions/common.py @@ -1,6 +1,7 @@ from typing import Literal from logging import getLogger +from kotonebot.backend.preprocessor import HsvColorFilter from kotonebot.tasks.actions.loading import loading from .. import R @@ -14,7 +15,7 @@ from kotonebot import ( sleep, Interval, ) -from ..game_ui import CommuEventButtonUI +from ..game_ui import CommuEventButtonUI, WhiteFilter from .pdorinku import acquire_pdorinku from kotonebot.backend.dispatch import SimpleDispatcher from kotonebot.tasks.actions.commu import handle_unread_commu @@ -55,7 +56,7 @@ def acquire_skill_card(): def select_p_item(): """ 前置条件:P物品选择对话框(受け取るPアイテムを選んでください;)\n - 结束条件:P物品获取动画 + 结束状态:P物品获取动画 """ # 前置条件 [screenshots/produce/in_produce/select_p_item.png] # 前置条件 [screenshots/produce/in_produce/claim_p_item.png] @@ -73,12 +74,12 @@ def select_p_item(): def hanlde_skill_card_enhance(): """ 前置条件:技能卡强化对话框\n - 结束条件:技能卡强化动画结束后瞬间 + 结束状态:技能卡强化动画结束后瞬间 :return: 是否成功处理对话框 """ # 前置条件 [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_skill_card_enhane.png] - # 结束条件 [screenshots/produce/in_produce/skill_card_enhance.png] + # 结束状态 [screenshots/produce/in_produce/skill_card_enhance.png] cards = image.find_multi([ R.InPurodyuusu.A, R.InPurodyuusu.M @@ -93,7 +94,7 @@ def hanlde_skill_card_enhance(): device.screenshot() if image.find(R.InPurodyuusu.ButtonEnhance, colored=True): device.click() - elif '強化' in ocr.ocr(rect=R.InPurodyuusu.BoxSkillCardEnhaced).squash().text: + elif image.find(R.InPurodyuusu.IconSkillCardEventBubble): device.click_center() break it.wait() @@ -104,11 +105,10 @@ AcquisitionType = Literal[ "PDrinkSelect", # P饮料主动领取 "PDrinkMax", # P饮料到达上限 "PSkillCardAcquire", # 技能卡领取 - "PSkillCardChange", # 技能卡更换 "PSkillCardSelect", # 技能卡选择 "PSkillCardEnhanced", # 技能卡强化 "PSkillCardEnhanceSelect", # 技能卡强化选择 - "PSkillCardRemove", # 技能卡移除 + "PSkillCardEvent", # 技能卡事件(随机强化、删除、更换) "PItemClaim", # P物品领取 "PItemSelect", # P物品选择 "Clear", # 目标达成 @@ -118,7 +118,7 @@ AcquisitionType = Literal[ "Loading", # 加载画面 ] -@measure_time(file_path='logs/acquisition.time.log') +@measure_time() @action('处理培育事件', screenshot_mode='manual') def acquisitions() -> AcquisitionType | None: """处理行动开始前和结束后可能需要处理的事件,直到到行动页面为止""" @@ -158,10 +158,10 @@ def acquisitions() -> AcquisitionType | None: logger.info("Leave button found") device.click(leave) return "PDrinkMax" - if ocr.find(contains('報酬'), rect=R.InPurodyuusu.BoxPDrinkMaxConfirmTitle): + if image.find(R.InPurodyuusu.TextPDrinkMaxConfirmTitle): logger.debug("PDrink max confirm found") device.screenshot() - if ocr.find(contains('報酬'), rect=R.InPurodyuusu.BoxPDrinkMaxConfirmTitle): + if image.find(R.InPurodyuusu.TextPDrinkMaxConfirmTitle): if confirm := image.find(R.Common.ButtonConfirm): logger.info("Confirm button found") device.click(confirm) @@ -190,7 +190,7 @@ def acquisitions() -> AcquisitionType | None: sleep(1) return "Clear" # 目标达成 NEXT - if ocr.find(regex('NEXT|next'), rect=R.InPurodyuusu.BoxGoalClearNext): + if image.find(R.InPurodyuusu.TextGoalClearNext, preprocessors=[WhiteFilter()]): logger.info("Goal clear (達成) next found") device.click_center() sleep(1) @@ -218,53 +218,44 @@ def acquisitions() -> AcquisitionType | None: # 物品选择对话框 logger.debug("Check award select dialog...") - if result := ocr.find(contains("受け取る"), rect=R.InPurodyuusu.BoxSelectPStuff): + if image.find(R.InPurodyuusu.TextClaim): logger.info("Award select dialog found.") - logger.debug(f"Dialog text: {result.text}") # P饮料选择 logger.debug("Check PDrink select...") - if "Pドリンク" in result.text: + if image.find(R.InPurodyuusu.TextPDrink): logger.info("PDrink select found") acquire_pdorinku(index=0) return "PDrinkSelect" # 技能卡选择 logger.debug("Check skill card select...") - if "スキルカード" in result.text: + if image.find(R.InPurodyuusu.TextSkillCard): logger.info("Acquire skill card found") acquire_skill_card() return "PSkillCardSelect" # P物品选择 logger.debug("Check PItem select...") - if "Pアイテム" in result.text: + if image.find(R.InPurodyuusu.TextPItem): logger.info("Acquire PItem found") select_p_item() return "PItemSelect" # 技能卡变更事件 + # 包括下面这些: + # 1. 技能卡更换 + # [screenshots/produce/in_produce/support_card_change.png] + # 2. 技能卡强化 + # [screenshots/produce/in_produce/skill_card_enhance.png] + # 3. 技能卡移除 + # [screenshots/produce/in_produce/skill_card_removal.png] logger.debug("Check skill card events...") - if result := ocr.ocr(rect=R.InPurodyuusu.BoxSkillCardEnhaced).squash(): - # 技能卡更换(支援卡效果) - # [screenshots/produce/in_produce/support_card_change.png] - if "チェンジ" in result.text: - logger.info("Change skill card found") - device.click(*bottom_pos) - return "PSkillCardChange" - # 技能卡强化 - # [screenshots/produce/in_produce/skill_card_enhance.png] - if "強化" in result.text: - logger.info("Enhance skill card found") - device.click(*bottom_pos) - return "PSkillCardEnhanced" - # 技能卡移除 - # [screenshots\produce\in_produce\skill_card_removal.png] - if "削除" in result.text: - logger.info("Remove skill card found") - device.click(*bottom_pos) - return "PSkillCardRemove" + if image.find(R.InPurodyuusu.IconSkillCardEventBubble): + device.click() # 不能 click_center,因为中间是技能卡 + return "PSkillCardEvent" # 技能卡获取 - # [res/sprites/jp/in_purodyuusu/screenshot_skill_card_acquired.png] + # [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_skill_card_acquired.png] + # 因为这个文本有缩放动画,因此暂时没法用模板匹配代替 if ocr.find("スキルカード獲得", rect=R.InPurodyuusu.BoxSkillCardAcquired): logger.info("Acquire skill card from loot box") device.click_center() diff --git a/kotonebot/tasks/game_ui.py b/kotonebot/tasks/game_ui.py index 5da068e..314f5d9 100644 --- a/kotonebot/tasks/game_ui.py +++ b/kotonebot/tasks/game_ui.py @@ -193,6 +193,12 @@ class CommuEventButtonUI: return ocr_result.squash().text class WhiteFilter(HsvColorFilter): + """ + 匹配时,只匹配图像和模板中的白色部分。 + + 此类用于识别空心/透明背景的白色图标或文字。 + """ + def __init__(self): super().__init__(WHITE_LOW, WHITE_HIGH)