diff --git a/resource/roguelike/Sami/ciphertext_board.json b/resource/roguelike/Sami/ciphertext_board.json new file mode 100644 index 0000000000..11217e5483 --- /dev/null +++ b/resource/roguelike/Sami/ciphertext_board.json @@ -0,0 +1,406 @@ +{ + "theme": "Sami", + "groups": [ + { + "usage": "SkipBattle", + "doc": "跳过战斗,刷钱和烧开水模式", + "pairs": [ + { + "up": [ + "伤痕" + ], + "down": [ + "空无" + ] + }, + { + "up": [ + "黜人", + "猎手", + "战士", + "萨满", + "英雄", + "源石", + "灌木", + "兽类", + "人类", + "眼睛", + "雪祀" + ], + "down": [ + "惊讶", + "疑惑", + "爱恋", + "繁衍" + ] + } + ] + }, + { + "usage": "Boss", + "doc": "有的用全用了", + "pairs": [ + { + "up": [ + "黜人", + "猎手", + "战士", + "萨满", + "英雄", + "雪祀", + "源石", + "灌木", + "兽类", + "人类", + "眼睛" + ], + "down": [ + "歌唱", + "沉默", + "朗诵", + "辩论", + "慰藉", + "告解", + "喜悦", + "惊讶", + "愤怒", + "疑惑", + "憧憬", + "爱恋", + "巡视", + "筑巢", + "捕猎", + "掠夺", + "繁衍", + "迁徙" + ] + } + ] + }, + { + "usage": "Battle", + "pairs": [ + { + "up": [ + "人类", + "兽类", + "灌木", + "砂石" + ], + "down": [ + "迁徙", + "掠夺", + "筑巢" + ] + }, + { + "up": [ + "英雄", + "萨满", + "战士", + "雪祀", + "猎手", + "黜人" + ], + "down": [ + "慰藉", + "告解", + "朗诵" + ] + } + ] + }, + { + "usage": "Trader", + "pairs": [ + { + "up": [ + "人类", + "兽类", + "灌木", + "砂石" + ], + "down": [ + "迁徙", + "掠夺", + "筑巢" + ] + }, + { + "up": [ + "大地", + "光芒", + "拱门", + "眼睛", + "水面" + ], + "down": [ + "喜悦", + "愤怒" + ] + }, + { + "up": [ + "眼睛" + ], + "down": [ + "憧憬" + ] + } + ] + }, + { + "usage": "Encounter", + "pairs": [ + { + "up": [ + "人类", + "兽类", + "灌木", + "砂石" + ], + "down": [ + "迁徙", + "掠夺", + "筑巢" + ] + }, + { + "up": [ + "树冠", + "大地", + "光芒", + "拱门", + "眼睛", + "水面" + ], + "down": [ + "惊讶", + "爱恋", + "喜悦", + "憧憬", + "朗诵" + ] + } + ] + }, + { + "usage": "Gambling", + "doc": "其他不期而遇节点", + "pairs": [ + { + "up": [ + "人类", + "兽类", + "灌木", + "砂石" + ], + "down": [ + "迁徙", + "掠夺", + "筑巢" + ] + }, + { + "up": [ + "大地", + "光芒", + "拱门", + "眼睛", + "水面" + ], + "down": [ + "惊讶", + "爱恋", + "喜悦", + "憧憬", + "朗诵" + ] + }, + { + "up": [ + "乔木", + "源石" + ], + "down": [ + "捕猎", + "繁衍", + "朗诵" + ] + }, + { + "up": [ + "树冠" + ], + "down": [ + "疑惑" + ] + } + ] + } + ], + "ciphertextBoard": [ + { + "name": "布局", + "ciphertextBoard": [ + { + "name": "黜人", + "effect": "选择所有右侧邻近的战斗节点" + }, + { + "name": "猎手", + "effect": "选择1处战斗节点" + }, + { + "name": "战士", + "effect": "选择1处战斗节点,再随机指定1处战斗节点" + }, + { + "name": "萨满", + "effect": "选择1处战斗节点,再随机指定2处战斗节点" + }, + { + "name": "雪祀", + "effect": "随机指定3处战斗节点,在深埋迷境中改为3处任意节点" + }, + { + "name": "英雄", + "effect": "选择所有战斗节点" + }, + { + "name": "树冠", + "effect": "选择1处不期而遇" + }, + { + "name": "水面", + "effect": "选择1处非战斗节点" + }, + { + "name": "眼睛", + "effect": "选择1处右侧邻近的节点" + }, + { + "name": "拱门", + "effect": "选择1处非战斗节点,再随机指定2处非战斗节点" + }, + { + "name": "光芒", + "effect": "随机指定3处非战斗节点" + }, + { + "name": "大地", + "effect": "选择所有非战斗节点" + }, + { + "name": "源石", + "effect": "选择1处任意节点" + }, + { + "name": "乔木", + "effect": "选择1处有纵向通路的节点" + }, + { + "name": "砂石", + "effect": "随机指定2处有纵向通路的节点" + }, + { + "name": "灌木", + "effect": "选择所有右侧1列内的节点" + }, + { + "name": "兽类", + "effect": "选择1处任意节点,再随机指定2处任意节点" + }, + { + "name": "人类", + "effect": "选择1处节点和它前后相连的所有节点" + }, + { + "name": "伤痕", + "effect": "选择1处右侧邻近的节点,只能和“空无”组合" + } + ] + }, + { + "name": "本因", + "ciphertextBoard": [ + { + "name": "歌唱", + "effect": "我方在此战斗时攻击速度+50 。协语:场上出现斗志昂扬无人机" + }, + { + "name": "沉默", + "effect": "我方在此战斗时最大生命+50% 。协语:场上出现友方盾卫" + }, + { + "name": "朗诵", + "effect": "经过后回复4目标生命 。协语:立即提升2目标生命上限" + }, + { + "name": "辩论", + "effect": "在此战斗时再部署时间-30% 。协语:1名精英干员临时加入编队" + }, + { + "name": "慰藉", + "effect": "经过此处后获得2希望 。协语:额外获得2希望" + }, + { + "name": "告解", + "effect": "经过此处后回复1目标生命 。协语:获得1个战斗类收藏品" + }, + { + "name": "喜悦", + "effect": "经过后获得8源石锭 。协语:获得2希望" + }, + { + "name": "惊讶", + "effect": "变为诡意行商 。协语:商品售价-50%" + }, + { + "name": "愤怒", + "effect": "此处招募时必出现4或5星临时招募 。协语:出现6星临时招募" + }, + { + "name": "疑惑", + "effect": "变为失与得 。协语:降低的坍缩值变为2点" + }, + { + "name": "憧憬", + "effect": "此处获得的源石锭变为2倍 。协语:目标生命、希望也变为2倍" + }, + { + "name": "爱恋", + "effect": "变为不期而遇 。协语:变为得偿所愿" + }, + { + "name": "巡视", + "effect": "接近时对其全面勘察,降低的坍缩值变为2点 。协语:降低的坍缩值变为3点" + }, + { + "name": "筑巢", + "effect": "经过后获得2护盾值 。协语:立即提升2目标生命上限" + }, + { + "name": "捕猎", + "effect": "变为紧急作战 。协语:经过后回复2目标生命" + }, + { + "name": "掠夺", + "effect": "经过后获得1源石锭、希望、护盾值 。协语:获得1抗干扰指数" + }, + { + "name": "繁衍", + "effect": "变为先行一步 。协语:经过后获得2希望" + }, + { + "name": "迁徙", + "effect": "经过后获得1抗干扰指数 。协语:变为树篱之途,且抗干扰指数升至上限" + }, + { + "name": "空无", + "effect": "变为木裂前兆,只能和“伤痕”组合" + } + ] + } + ] +} \ No newline at end of file diff --git a/resource/tasks.json b/resource/tasks.json index 960c7e5a17..c39412496b 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -61,6 +61,60 @@ ], "maxTimes": 50 }, + "SlowlySwipeToTheUp": { + "algorithm": "JustReturn", + "action": "Swipe", + "postDelay": 200, + "specificRect": [ + 600, + 510, + 100, + 100 + ], + "rectMove": [ + 600, + 0, + 100, + 100 + ], + "specialParams": [ + 200, + 1, + 2, + 0 + ], + "next": [ + "#next" + ], + "maxTimes": 50 + }, + "SlowlySwipeToTheDown": { + "algorithm": "JustReturn", + "action": "Swipe", + "postDelay": 200, + "specificRect": [ + 600, + 145, + 100, + 100 + ], + "rectMove": [ + 600, + 610, + 100, + 100 + ], + "specialParams": [ + 200, + 1, + 2, + 0 + ], + "next": [ + "#next" + ], + "maxTimes": 50 + }, "SwipeToTheLeft": { "algorithm": "JustReturn", "action": "Swipe", @@ -9881,6 +9935,43 @@ 47 ] }, + "RoguelikeCiphertextBoardSlowlySwipeToTheUp": { + "baseTask": "SlowlySwipeToTheUp", + "specificRect": [ + 180, + 580, + 20, + 20 + ], + "rectMove": [ + 180, + 110, + 20, + 20 + ], + "specialParams": [ + 200, + 1, + 2, + 0 + ], + "postDelay": 500 + }, + "RoguelikeCiphertextBoardSwipeToTheDown": { + "baseTask": "SwipeToTheDown", + "specificRect": [ + 180, + 110, + 20, + 20 + ], + "rectMove": [ + 180, + 570, + 20, + 20 + ] + }, "RoguelikeControlTaskPlugin-ExitThenStop": { "Doc": "本任务注册了插件 RoguelikeControlTaskPlugin", "algorithm": "JustReturn" @@ -13291,6 +13382,195 @@ "Sami@Roguelike@ChooseOperConfirm#next" ] }, + "Sami@Roguelike@CiphertextBoard": { + "cache": false, + "action": "ClickSelf", + "roi": [ + 639, + 599, + 299, + 121 + ], + "postDelay": 2000 + }, + "Sami@Roguelike@CiphertextBoardBack": { + "action": "ClickSelf", + "roi": [ + 0, + 0, + 146, + 144 + ], + "postDelay": 2000 + }, + "Sami@Roguelike@CiphertextBoardGain": { + "doc": "本任务注册插件RoguelikeCiphertextBoardGain", + "template": "Sami@Roguelike@CiphertextBoardGain", + "action": "ClickRect", + "specificRect": [ + 611, + 496, + 60, + 51 + ], + "postDelay": 500, + "roi": [ + 333, + 201, + 676, + 307 + ], + "maskRange": [ + 1, + 255 + ], + "next": [ + "Sami@Roguelike@CiphertextBoardGain", + "Sami@Roguelike@SquadConfirm#next" + ] + }, + "Sami@Roguelike@CiphertextBoardGainOcr": { + "algorithm": "OcrDetect", + "action": "DoNothing", + "cache": false, + "roi": [ + 584, + 261, + 315, + 46 + ], + "text": [ + "黜人", + "猎手", + "战士", + "萨满", + "雪祀", + "英雄", + "树冠", + "水面", + "眼睛", + "拱门", + "光芒", + "大地", + "源石", + "乔木", + "砂石", + "灌木", + "兽类", + "人类", + "伤痕", + "歌唱", + "沉默", + "朗诵", + "辩论", + "慰藉", + "告解", + "喜悦", + "惊讶", + "愤怒", + "疑惑", + "憧憬", + "爱恋", + "巡视", + "筑巢", + "捕猎", + "繁衍", + "掠夺", + "迁徙", + "空无" + ], + "ocrReplace": [ + [ + "黜", + "黜人" + ] + ] + }, + "Sami@Roguelike@CiphertextBoardGainOcrAfterCombat": { + "baseTask": "Sami@Roguelike@CiphertextBoardGainOcr", + "roi": [ + 44, + 309, + 1195, + 124 + ] + }, + "Sami@Roguelike@CiphertextBoardUseConfirm": { + "algorithm": "OcrDetect", + "action": "ClickSelf", + "text": [ + "开始宣告" + ], + "roi": [ + 953, + 597, + 302, + 113 + ], + "postDelay": 2000 + }, + "Sami@Roguelike@CiphertextBoardUseOcr": { + "algorithm": "OcrDetect", + "action": "DoNothing", + "cache": false, + "text": [ + "布局" + ], + "roi": [ + 38, + 64, + 85, + 518 + ], + "rectMove": [ + 150, + -50, + 50, + 5 + ], + "specificRect_Doc": "x拿来当文字灰度二值化下限用", + "specificRect": [ + 170, + 0, + 0, + 0 + ] + }, + "Sami@Roguelike@CiphertextBoardUseOnStage": { + "cache": false, + "doc": "缺紧急战斗和先行一步", + "action": "ClickSelf", + "template": [ + "Sami@Roguelike@CiphertextBoardUseOnGambling.png", + "Sami@Roguelike@CiphertextBoardUseOnWindAndRain.png", + "Sami@Roguelike@CiphertextBoardUseOnEmergencyTransportation.png", + "Sami@Roguelike@CiphertextBoardUseOnCombatDps.png", + "Sami@Roguelike@CiphertextBoardUseOnMysteriousPresage.png", + "Sami@Roguelike@CiphertextBoardUseOnEmergencyDps.png", + "Sami@Roguelike@CiphertextBoardUseOnDreadfulFoe-5.png", + "Sami@Roguelike@CiphertextBoardUseOnFerociousPresage.png", + "Sami@Roguelike@CiphertextBoardUseOnEncounter.png", + "Sami@Roguelike@CiphertextBoardUseOnTrader.png" + ], + "templThreshold": [ + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7 + ], + "roi": [ + 429, + 111, + 844, + 477 + ] + }, "Sami@Roguelike@CloseCollection": { "next": [ "Sami@Roguelike@LastReward", @@ -13429,31 +13709,6 @@ }, "Sami@Roguelike@GamePassSkip2": {}, "Sami@Roguelike@GamePassTheEndConfirm": {}, - "Sami@Roguelike@GetCiphertextBoard": { - "template": "Sami@Roguelike@GetCiphertextBoard", - "action": "ClickRect", - "specificRect": [ - 611, - 496, - 60, - 51 - ], - "postDelay": 500, - "roi": [ - 333, - 201, - 676, - 307 - ], - "maskRange": [ - 1, - 255 - ], - "next": [ - "Sami@Roguelike@GetCiphertextBoard", - "Sami@Roguelike@SquadConfirm#next" - ] - }, "Sami@Roguelike@GetDrop1": {}, "Sami@Roguelike@GetDrop2": {}, "Sami@Roguelike@GetDrop3": {}, @@ -13487,14 +13742,14 @@ "Doc": "密文板三选一", "template": "Sami@Roguelike@GetDropSelectReward2.png", "cache": false, - "action": "ClickSelf", + "action": "DoNothing", "roi": [ 0, 420, 1280, 175 ], - "postDelay": 1000, + "postDelay": 800, "next": [ "Sami@Roguelike@GetDropSelectReward2", "Sami@Roguelike@ChooseOperFlag", @@ -13599,7 +13854,7 @@ "Sami@Roguelike@DialogSkip", "Sami@Roguelike@Stages#next", "Sami@Roguelike@MapObject", - "Sami@Roguelike@GetCiphertextBoard" + "Sami@Roguelike@CiphertextBoardGain" ] }, "Sami@Roguelike@SquadDefault": {}, @@ -14135,18 +14390,18 @@ "Sami@Roguelike@StageVerticalSafeHouseAI6", "Sami@Roguelike@StageVerticalBoons", "Sami@Roguelike@StageVerticalBoonsAI6", - "Sami@Roguelike@StageVerticalEncounter", - "Sami@Roguelike@StageVerticalEncounterAI6", "Sami@Roguelike@StageVerticalTrader", "Sami@Roguelike@StageVerticalTraderAI6", "Sami@Roguelike@StageSafeHouse", "Sami@Roguelike@StageSafeHouseAI6", "Sami@Roguelike@StageBoons", "Sami@Roguelike@StageBoonsAI6", - "Sami@Roguelike@StageEncounter", - "Sami@Roguelike@StageEncounterAI6", "Sami@Roguelike@StageTrader", "Sami@Roguelike@StageTraderAI6", + "Sami@Roguelike@StageEncounter", + "Sami@Roguelike@StageEncounterAI6", + "Sami@Roguelike@StageVerticalEncounter", + "Sami@Roguelike@StageVerticalEncounterAI6", "Sami@Roguelike@StageVerticalProphecy", "Sami@Roguelike@StageVerticalProphecyAI6", "Sami@Roguelike@StageWindAndRain", diff --git a/resource/template/Sami@Roguelike@CiphertextBoard.png b/resource/template/Sami@Roguelike@CiphertextBoard.png new file mode 100644 index 0000000000..623b4de2de Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoard.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardBack.png b/resource/template/Sami@Roguelike@CiphertextBoardBack.png new file mode 100644 index 0000000000..dfbcf9cfc6 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardBack.png differ diff --git a/resource/template/Sami@Roguelike@GetCiphertextBoard.png b/resource/template/Sami@Roguelike@CiphertextBoardGain.png similarity index 100% rename from resource/template/Sami@Roguelike@GetCiphertextBoard.png rename to resource/template/Sami@Roguelike@CiphertextBoardGain.png diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnCombatDps.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnCombatDps.png new file mode 100644 index 0000000000..061bacaa5f Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnCombatDps.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnDreadfulFoe-5.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnDreadfulFoe-5.png new file mode 100644 index 0000000000..3c0967981e Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnDreadfulFoe-5.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnEmergencyDps.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnEmergencyDps.png new file mode 100644 index 0000000000..ea6108966a Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnEmergencyDps.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnEmergencyTransportation.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnEmergencyTransportation.png new file mode 100644 index 0000000000..adfe33fba2 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnEmergencyTransportation.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnEncounter.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnEncounter.png new file mode 100644 index 0000000000..b4fb242754 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnEncounter.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnFerociousPresage.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnFerociousPresage.png new file mode 100644 index 0000000000..4abea6c446 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnFerociousPresage.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnGambling.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnGambling.png new file mode 100644 index 0000000000..cae26d6948 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnGambling.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnMysteriousPresage.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnMysteriousPresage.png new file mode 100644 index 0000000000..e5fb5e05dc Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnMysteriousPresage.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnTrader.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnTrader.png new file mode 100644 index 0000000000..9921d6bf40 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnTrader.png differ diff --git a/resource/template/Sami@Roguelike@CiphertextBoardUseOnWindAndRain.png b/resource/template/Sami@Roguelike@CiphertextBoardUseOnWindAndRain.png new file mode 100644 index 0000000000..f16a4dbf12 Binary files /dev/null and b/resource/template/Sami@Roguelike@CiphertextBoardUseOnWindAndRain.png differ diff --git a/resource/template/Sami@Roguelike@StageBoons.png b/resource/template/Sami@Roguelike@StageBoons.png index fe347179a7..6f810a196d 100644 Binary files a/resource/template/Sami@Roguelike@StageBoons.png and b/resource/template/Sami@Roguelike@StageBoons.png differ diff --git a/resource/template/Sami@Roguelike@StageBoonsAI6.png b/resource/template/Sami@Roguelike@StageBoonsAI6.png index 0e3c660b8e..f52628ccd9 100644 Binary files a/resource/template/Sami@Roguelike@StageBoonsAI6.png and b/resource/template/Sami@Roguelike@StageBoonsAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageBoskyPassage.png b/resource/template/Sami@Roguelike@StageBoskyPassage.png index 3443403302..5e7aff2beb 100644 Binary files a/resource/template/Sami@Roguelike@StageBoskyPassage.png and b/resource/template/Sami@Roguelike@StageBoskyPassage.png differ diff --git a/resource/template/Sami@Roguelike@StageBoskyPassageAI6.png b/resource/template/Sami@Roguelike@StageBoskyPassageAI6.png index bc430abc91..cfa85804ea 100644 Binary files a/resource/template/Sami@Roguelike@StageBoskyPassageAI6.png and b/resource/template/Sami@Roguelike@StageBoskyPassageAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageCombatDps.png b/resource/template/Sami@Roguelike@StageCombatDps.png index 543dd374a9..7bbafa4010 100644 Binary files a/resource/template/Sami@Roguelike@StageCombatDps.png and b/resource/template/Sami@Roguelike@StageCombatDps.png differ diff --git a/resource/template/Sami@Roguelike@StageCombatDpsAI6.png b/resource/template/Sami@Roguelike@StageCombatDpsAI6.png index 069a349037..a0fca76df0 100644 Binary files a/resource/template/Sami@Roguelike@StageCombatDpsAI6.png and b/resource/template/Sami@Roguelike@StageCombatDpsAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageDreadfulFoe-5.png b/resource/template/Sami@Roguelike@StageDreadfulFoe-5.png index d268367893..cd893f3926 100644 Binary files a/resource/template/Sami@Roguelike@StageDreadfulFoe-5.png and b/resource/template/Sami@Roguelike@StageDreadfulFoe-5.png differ diff --git a/resource/template/Sami@Roguelike@StageDreadfulFoe.png b/resource/template/Sami@Roguelike@StageDreadfulFoe.png index 0f822ea018..c7875ea9af 100644 Binary files a/resource/template/Sami@Roguelike@StageDreadfulFoe.png and b/resource/template/Sami@Roguelike@StageDreadfulFoe.png differ diff --git a/resource/template/Sami@Roguelike@StageEmergencyDps.png b/resource/template/Sami@Roguelike@StageEmergencyDps.png index c5922bccb0..60a00afdb0 100644 Binary files a/resource/template/Sami@Roguelike@StageEmergencyDps.png and b/resource/template/Sami@Roguelike@StageEmergencyDps.png differ diff --git a/resource/template/Sami@Roguelike@StageEmergencyDpsAI6.png b/resource/template/Sami@Roguelike@StageEmergencyDpsAI6.png index 250b340024..079e48dc68 100644 Binary files a/resource/template/Sami@Roguelike@StageEmergencyDpsAI6.png and b/resource/template/Sami@Roguelike@StageEmergencyDpsAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageEmergencyTransportation.png b/resource/template/Sami@Roguelike@StageEmergencyTransportation.png index 1642b9a23e..8cd535e3a7 100644 Binary files a/resource/template/Sami@Roguelike@StageEmergencyTransportation.png and b/resource/template/Sami@Roguelike@StageEmergencyTransportation.png differ diff --git a/resource/template/Sami@Roguelike@StageEmergencyTransportationAI6.png b/resource/template/Sami@Roguelike@StageEmergencyTransportationAI6.png index f0803bcdf3..d693955ef7 100644 Binary files a/resource/template/Sami@Roguelike@StageEmergencyTransportationAI6.png and b/resource/template/Sami@Roguelike@StageEmergencyTransportationAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageEncounter.png b/resource/template/Sami@Roguelike@StageEncounter.png index 453c55772a..858d25b804 100644 Binary files a/resource/template/Sami@Roguelike@StageEncounter.png and b/resource/template/Sami@Roguelike@StageEncounter.png differ diff --git a/resource/template/Sami@Roguelike@StageEncounterAI6.png b/resource/template/Sami@Roguelike@StageEncounterAI6.png index aa89ad5cfe..84e664e78e 100644 Binary files a/resource/template/Sami@Roguelike@StageEncounterAI6.png and b/resource/template/Sami@Roguelike@StageEncounterAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageFerociousPresage.png b/resource/template/Sami@Roguelike@StageFerociousPresage.png index 5b773dcfab..842549ea8b 100644 Binary files a/resource/template/Sami@Roguelike@StageFerociousPresage.png and b/resource/template/Sami@Roguelike@StageFerociousPresage.png differ diff --git a/resource/template/Sami@Roguelike@StageGambling.png b/resource/template/Sami@Roguelike@StageGambling.png index d0b7c3417a..1cd80d0c53 100644 Binary files a/resource/template/Sami@Roguelike@StageGambling.png and b/resource/template/Sami@Roguelike@StageGambling.png differ diff --git a/resource/template/Sami@Roguelike@StageGamblingAI6.png b/resource/template/Sami@Roguelike@StageGamblingAI6.png index 1aac78fa79..af96dfc6df 100644 Binary files a/resource/template/Sami@Roguelike@StageGamblingAI6.png and b/resource/template/Sami@Roguelike@StageGamblingAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageMysteriousPresage.png b/resource/template/Sami@Roguelike@StageMysteriousPresage.png index 59689a6d1d..218093f572 100644 Binary files a/resource/template/Sami@Roguelike@StageMysteriousPresage.png and b/resource/template/Sami@Roguelike@StageMysteriousPresage.png differ diff --git a/resource/template/Sami@Roguelike@StageProphecyAI6.png b/resource/template/Sami@Roguelike@StageProphecyAI6.png index 4edde3cd2d..7e456376fa 100644 Binary files a/resource/template/Sami@Roguelike@StageProphecyAI6.png and b/resource/template/Sami@Roguelike@StageProphecyAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageSafeHouse.png b/resource/template/Sami@Roguelike@StageSafeHouse.png index 65a862c847..8f39b0d37c 100644 Binary files a/resource/template/Sami@Roguelike@StageSafeHouse.png and b/resource/template/Sami@Roguelike@StageSafeHouse.png differ diff --git a/resource/template/Sami@Roguelike@StageSafeHouseAI6.png b/resource/template/Sami@Roguelike@StageSafeHouseAI6.png index 5428395a8d..757d028486 100644 Binary files a/resource/template/Sami@Roguelike@StageSafeHouseAI6.png and b/resource/template/Sami@Roguelike@StageSafeHouseAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageTrader.png b/resource/template/Sami@Roguelike@StageTrader.png index 653120c7a4..f40e92bb43 100644 Binary files a/resource/template/Sami@Roguelike@StageTrader.png and b/resource/template/Sami@Roguelike@StageTrader.png differ diff --git a/resource/template/Sami@Roguelike@StageTraderAI6.png b/resource/template/Sami@Roguelike@StageTraderAI6.png index e88c72ab4a..3aea2dea2d 100644 Binary files a/resource/template/Sami@Roguelike@StageTraderAI6.png and b/resource/template/Sami@Roguelike@StageTraderAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalBoonsAI6.png b/resource/template/Sami@Roguelike@StageVerticalBoonsAI6.png index 3edb2f3dd0..28bab08c3f 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalBoonsAI6.png and b/resource/template/Sami@Roguelike@StageVerticalBoonsAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalCombatDps.png b/resource/template/Sami@Roguelike@StageVerticalCombatDps.png index 708a9f53b9..c9f169d4dc 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalCombatDps.png and b/resource/template/Sami@Roguelike@StageVerticalCombatDps.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalEmergencyDps.png b/resource/template/Sami@Roguelike@StageVerticalEmergencyDps.png index ff98649403..cde8ae6499 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalEmergencyDps.png and b/resource/template/Sami@Roguelike@StageVerticalEmergencyDps.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalGamblingAI6.png b/resource/template/Sami@Roguelike@StageVerticalGamblingAI6.png index 6f87ad1212..aad66e5e32 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalGamblingAI6.png and b/resource/template/Sami@Roguelike@StageVerticalGamblingAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalProphecy.png b/resource/template/Sami@Roguelike@StageVerticalProphecy.png index 7ee72ba935..1d49768158 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalProphecy.png and b/resource/template/Sami@Roguelike@StageVerticalProphecy.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalProphecyAI6.png b/resource/template/Sami@Roguelike@StageVerticalProphecyAI6.png index 6175eb2479..a26a5535bf 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalProphecyAI6.png and b/resource/template/Sami@Roguelike@StageVerticalProphecyAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageVerticalSafeHouseAI6.png b/resource/template/Sami@Roguelike@StageVerticalSafeHouseAI6.png index db992fb8ce..e5bdceba8c 100644 Binary files a/resource/template/Sami@Roguelike@StageVerticalSafeHouseAI6.png and b/resource/template/Sami@Roguelike@StageVerticalSafeHouseAI6.png differ diff --git a/resource/template/Sami@Roguelike@StageWindAndRain.png b/resource/template/Sami@Roguelike@StageWindAndRain.png index 5644d30ea1..8e2945746f 100644 Binary files a/resource/template/Sami@Roguelike@StageWindAndRain.png and b/resource/template/Sami@Roguelike@StageWindAndRain.png differ diff --git a/resource/template/Sami@Roguelike@StageWindAndRainAI6.png b/resource/template/Sami@Roguelike@StageWindAndRainAI6.png index 930ce418a2..46349aeb5b 100644 Binary files a/resource/template/Sami@Roguelike@StageWindAndRainAI6.png and b/resource/template/Sami@Roguelike@StageWindAndRainAI6.png differ diff --git a/src/MaaCore/Config/ResourceLoader.cpp b/src/MaaCore/Config/ResourceLoader.cpp index 178fd0c02c..243b4617c8 100644 --- a/src/MaaCore/Config/ResourceLoader.cpp +++ b/src/MaaCore/Config/ResourceLoader.cpp @@ -15,6 +15,7 @@ #include "Miscellaneous/StageDropsConfig.h" #include "Miscellaneous/TilePack.h" #include "OnnxSessions.h" +#include "Roguelike/RoguelikeCiphertextBoardConfig.h" #include "Roguelike/RoguelikeCopilotConfig.h" #include "Roguelike/RoguelikeRecruitConfig.h" #include "Roguelike/RoguelikeShoppingConfig.h" @@ -184,6 +185,8 @@ bool asst::ResourceLoader::load(const std::filesystem::path& path) LoadResourceAndCheckRet(RoguelikeStageEncounterConfig, "roguelike"_p / "Mizuki"_p / "encounter_for_deposit.json"_p); LoadResourceAndCheckRet(RoguelikeStageEncounterConfig, "roguelike"_p / "Sami"_p / "encounter_for_deposit.json"_p); + LoadResourceAndCheckRet(RoguelikeCiphertextBoardConfig, "roguelike"_p / "Sami"_p / "ciphertext_board.json"_p); + #undef LoadTemplByConfigAndCheckRet #undef LoadResourceAndCheckRet #undef LoadCacheWithoutRet diff --git a/src/MaaCore/Config/Roguelike/RoguelikeCiphertextBoardConfig.cpp b/src/MaaCore/Config/Roguelike/RoguelikeCiphertextBoardConfig.cpp new file mode 100644 index 0000000000..15165aeb41 --- /dev/null +++ b/src/MaaCore/Config/Roguelike/RoguelikeCiphertextBoardConfig.cpp @@ -0,0 +1,35 @@ +#include "RoguelikeCiphertextBoardConfig.h" + +#include + +#include "Utils/Logger.hpp" + +bool asst::RoguelikeCiphertextBoardConfig::parse(const json::value& json) +{ + LogTraceFunction; + + const std::string theme = json.at("theme").as_string(); + m_ciphertext_board_combination.erase(theme); + + for (const auto& combination_json : json.at("groups").as_array()) { + + RoguelikeCiphertextBoardCombination combination; + combination.usage = combination_json.get("usage", "none"); + + for (const auto& pairs : combination_json.at("pairs").as_array()) { + CiphertextBoardPair pair; + const json::array& up_boards = pairs.at("up").as_array(); + for (const auto& board : up_boards) { + pair.up_board.emplace_back(board.as_string()); + } + const json::array& down_boards = pairs.at("down").as_array(); + for (const auto& board : down_boards) { + pair.down_board.emplace_back(board.as_string()); + } + combination.pairs.emplace_back(pair); + } + m_ciphertext_board_combination[theme].emplace_back(std::move(combination)); + } + + return true; +} diff --git a/src/MaaCore/Config/Roguelike/RoguelikeCiphertextBoardConfig.h b/src/MaaCore/Config/Roguelike/RoguelikeCiphertextBoardConfig.h new file mode 100644 index 0000000000..b6458f8fd2 --- /dev/null +++ b/src/MaaCore/Config/Roguelike/RoguelikeCiphertextBoardConfig.h @@ -0,0 +1,42 @@ +#pragma once + +#include "Config/AbstractConfig.h" + +#include + +#include "Common/AsstBattleDef.h" + +namespace asst +{ + // 板子组合 + struct CiphertextBoardPair + { + std::vector up_board; // 上板子 + std::vector down_board; // 下板子 + }; + struct RoguelikeCiphertextBoardCombination + { + std::string usage; // 适用的节点类型和用法 + std::vector pairs; // 适用的板子组合 + }; + + class RoguelikeCiphertextBoardConfig final : public SingletonHolder, + public AbstractConfig + { + public: + virtual ~RoguelikeCiphertextBoardConfig() override = default; + + const auto& get_combination(const std::string& theme) const noexcept + { + return m_ciphertext_board_combination.at(theme); + } + + private: + virtual bool parse(const json::value& json) override; + + std::unordered_map> + m_ciphertext_board_combination; + }; + + inline static auto& RoguelikeCiphertextBoard = RoguelikeCiphertextBoardConfig::get_instance(); +} diff --git a/src/MaaCore/MaaCore.vcxproj b/src/MaaCore/MaaCore.vcxproj index 6650b2f15f..0b94087cb7 100644 --- a/src/MaaCore/MaaCore.vcxproj +++ b/src/MaaCore/MaaCore.vcxproj @@ -48,12 +48,14 @@ + + @@ -86,6 +88,8 @@ + + @@ -254,6 +258,8 @@ + + diff --git a/src/MaaCore/MaaCore.vcxproj.filters b/src/MaaCore/MaaCore.vcxproj.filters index 109baf578b..9410ef094e 100644 --- a/src/MaaCore/MaaCore.vcxproj.filters +++ b/src/MaaCore/MaaCore.vcxproj.filters @@ -216,6 +216,9 @@ Source\Resource + + Source\Resource\Roguelike + Source\Resource\Roguelike @@ -441,6 +444,12 @@ Source\Task\Roguelike + + Source\Task\Roguelike + + + Source\Task\Roguelike + Source\Task\Roguelike @@ -731,6 +740,9 @@ Source\Resource + + Source\Resource\Roguelike + Source\Resource\Roguelike @@ -905,6 +917,12 @@ Source\Task\Roguelike + + Source\Task\Roguelike + + + Source\Task\Roguelike + Source\Task\Roguelike diff --git a/src/MaaCore/Status.h b/src/MaaCore/Status.h index d0b577c32f..a55c63a9df 100644 --- a/src/MaaCore/Status.h +++ b/src/MaaCore/Status.h @@ -55,6 +55,8 @@ namespace asst static inline const std::string RoguelikeMode = "RoguelikeMode"; static inline const std::string RoguelikeDifficulty = "RoguelikeDifficulty"; + static inline const std::string RoguelikeCiphertextBoardOverview = "RoguelikeCiphertextBoardOverview"; + static inline const std::string ProcessTaskLastTimePrefix = "#LastTime#"; private: diff --git a/src/MaaCore/Task/Interface/RoguelikeTask.cpp b/src/MaaCore/Task/Interface/RoguelikeTask.cpp index c1dc8f36cf..c9b420a61f 100644 --- a/src/MaaCore/Task/Interface/RoguelikeTask.cpp +++ b/src/MaaCore/Task/Interface/RoguelikeTask.cpp @@ -18,6 +18,10 @@ #include "Task/Roguelike/RoguelikeSkillSelectionTaskPlugin.h" #include "Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h" #include "Task/Roguelike/RoguelikeStrategyChangeTaskPlugin.h" + +#include "Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.h" +#include "Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.h" + #include "Utils/Logger.hpp" asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, Assistant* inst) @@ -49,6 +53,10 @@ asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, Assistant* inst m_difficulty_selection_plugin_ptr = m_roguelike_task_ptr->register_plugin(); m_strategy_change_plugin_ptr = m_roguelike_task_ptr->register_plugin(); + m_ciphertext_board_gain_plugin_ptr = + m_roguelike_task_ptr->register_plugin(); + m_ciphertext_board_use_plugin_ptr = m_roguelike_task_ptr->register_plugin(); + // 这个任务如果卡住会放弃当前的肉鸽并重新开始,所以多添加一点。先这样凑合用 for (int i = 0; i != 100; ++i) { m_subtasks.emplace_back(m_roguelike_task_ptr); @@ -77,6 +85,9 @@ bool asst::RoguelikeTask::set_params(const json::value& params) } } + m_ciphertext_board_gain_plugin_ptr->set_roguelike_theme(theme); + m_ciphertext_board_use_plugin_ptr->set_roguelike_theme(theme); + m_roguelike_task_ptr->set_tasks({ theme + "@Roguelike@Begin" }); // 0 - 刷经验,尽可能稳定地打更多层数,不期而遇采用激进策略 diff --git a/src/MaaCore/Task/Interface/RoguelikeTask.h b/src/MaaCore/Task/Interface/RoguelikeTask.h index 0f31f5f7b5..77ef9a8d81 100644 --- a/src/MaaCore/Task/Interface/RoguelikeTask.h +++ b/src/MaaCore/Task/Interface/RoguelikeTask.h @@ -19,6 +19,9 @@ namespace asst class RoguelikeStageEncounterTaskPlugin; class RoguelikeStrategyChangeTaskPlugin; + class RoguelikeCiphertextBoardGainTaskPlugin; + class RoguelikeCiphertextBoardUseTaskPlugin; + class RoguelikeTask : public InterfaceTask { public: @@ -45,5 +48,8 @@ namespace asst std::shared_ptr m_shopping_plugin_ptr = nullptr; std::shared_ptr m_stage_encounter_plugin_ptr = nullptr; std::shared_ptr m_strategy_change_plugin_ptr = nullptr; + + std::shared_ptr m_ciphertext_board_gain_plugin_ptr = nullptr; + std::shared_ptr m_ciphertext_board_use_plugin_ptr = nullptr; }; } diff --git a/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.cpp new file mode 100644 index 0000000000..04e2eec837 --- /dev/null +++ b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.cpp @@ -0,0 +1,82 @@ +#include "RoguelikeCiphertextBoardGainTaskPlugin.h" + +#include "Controller/Controller.h" +#include "Status.h" +#include "Utils/Logger.hpp" +#include "Vision/OCRer.h" + +bool asst::RoguelikeCiphertextBoardGainTaskPlugin::verify(AsstMsg msg, const json::value& details) const +{ + if (msg != AsstMsg::SubTaskStart || details.get("subtask", std::string()) != "ProcessTask") { + return false; + } + + if (m_roguelike_theme.empty()) { + Log.error("Roguelike name doesn't exist!"); + return false; + } + if (m_roguelike_theme != "Sami") { + return false; + } + const std::string roguelike_name = m_roguelike_theme + "@"; + const std::string& task = details.get("details", "task", ""); + std::string_view task_view = task; + + if (task_view.starts_with(roguelike_name)) { + task_view.remove_prefix(roguelike_name.length()); + } + if (task_view == "Roguelike@CiphertextBoardGain") { + m_ocr_after_combat = false; + return true; + } + if (task_view == "Roguelike@StageEncounterSpecialClose") { + m_ocr_after_combat = false; + return true; + } + if (task_view == "Roguelike@GetDropSelectReward2") { + m_ocr_after_combat = true; + return true; + } + /* 可能是没点科技树会单独掉一个密文板,很快能点出来,暂时不做识别 + if (task_view == "Roguelike@GetDrop2") { + m_ocr_after_combat = true; + return true; + }*/ + else { + return false; + } +} + +bool asst::RoguelikeCiphertextBoardGainTaskPlugin::_run() +{ + LogTraceFunction; + + std::string theme = m_roguelike_theme; + std::string mode = status()->get_properties(Status::RoguelikeMode).value(); + + auto image = ctrler()->get_image(); + + OCRer analyzer(image); + std::string task_name = m_ocr_after_combat ? theme + "@Roguelike@CiphertextBoardGainOcrAfterCombat" + : theme + "@Roguelike@CiphertextBoardGainOcr"; + analyzer.set_task_info(task_name); + + if (!analyzer.analyze()) { + return false; + } + std::string ciphertext_board = analyzer.get_result().front().text; + + std::string overview_str = + status()->get_str(Status::RoguelikeCiphertextBoardOverview).value_or(json::value().to_string()); + json::value overview_json = json::parse(overview_str).value_or(json::value()); + auto& overview = overview_json.as_array(); + // 把ciphertext_board存到overview里 + overview.emplace_back(ciphertext_board); + status()->set_str(Status::RoguelikeCiphertextBoardOverview, overview.to_string()); + + if (m_ocr_after_combat) { + ctrler()->click(analyzer.get_result().front().rect); + } + + return true; +} diff --git a/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.h new file mode 100644 index 0000000000..e2ab810e69 --- /dev/null +++ b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardGainTaskPlugin.h @@ -0,0 +1,23 @@ +#pragma once +#include "RoguelikeConfig.h" +#include "Task/AbstractTaskPlugin.h" + +namespace asst +{ + class RoguelikeCiphertextBoardGainTaskPlugin : public AbstractTaskPlugin, public RoguelikeConfig + { + public: + using AbstractTaskPlugin::AbstractTaskPlugin; + virtual ~RoguelikeCiphertextBoardGainTaskPlugin() override = default; + + public: + virtual bool verify(AsstMsg msg, const json::value& details) const override; + + protected: + virtual bool _run() override; + + private: + // 战斗后识别密文板 + mutable bool m_ocr_after_combat = false; + }; +} diff --git a/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.cpp new file mode 100644 index 0000000000..28dd609774 --- /dev/null +++ b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.cpp @@ -0,0 +1,223 @@ +#include "RoguelikeCiphertextBoardUseTaskPlugin.h" + +#include "Config/Roguelike/RoguelikeCiphertextBoardConfig.h" +#include "Config/TaskData.h" +#include "Controller/Controller.h" +#include "Status.h" +#include "Task/ProcessTask.h" +#include "Utils/Logger.hpp" +#include "Vision/OCRer.h" + +bool asst::RoguelikeCiphertextBoardUseTaskPlugin::verify(AsstMsg msg, const json::value& details) const +{ + if (msg != AsstMsg::SubTaskStart || details.get("subtask", std::string()) != "ProcessTask") { + return false; + } + + if (m_roguelike_theme.empty()) { + Log.error("Roguelike name doesn't exist!"); + return false; + } + if (m_roguelike_theme != "Sami") { + return false; + } + std::string mode = status()->get_properties(Status::RoguelikeMode).value(); + std::string task_name_pre = m_roguelike_theme + "@Roguelike@Stage"; + const std::string& task = details.get("details", "task", ""); + std::string_view task_view = task; + + if (task_view.starts_with(task_name_pre)) { + task_view.remove_prefix(task_name_pre.length()); + } + // 不知道是不是不对纵向节点用比较好,先写上 + task_name_pre = "task_name_pre"; + if (task_view.starts_with("Vertical")) { + task_view.remove_prefix(task_name_pre.length()); + } + std::string task_name_suf = "AI6"; + if (task_view.ends_with(task_name_suf)) { + task_view.remove_suffix(task_name_suf.length()); + } + if (task_view == "CombatDps" || task_view == "EmergencyDps" || task_view == "FerociousPresage") { + if (mode == "1" || mode == "4") { + m_stage = "SkipBattle"; + } + else if (mode == "0") { + m_stage = "Battle"; + } + return true; + } + if (task_view == "DreadfulFoe-5" && mode == "0") { + m_stage = "Boss"; + return true; + } + if (task_view == "Trader" && mode == "0") { + m_stage = "Trader"; + return true; + } + if (task_view == "Encounter" && mode == "0") { + m_stage = "Encounter"; + return true; + } + if ((task_view == "Gambling" || task_view == "EmergencyTransportation" || task_view == "WindAndRain") && + mode == "0") { + m_stage = "Gambling"; + return true; + } + else { + return false; + } +} + +bool asst::RoguelikeCiphertextBoardUseTaskPlugin::_run() +{ + LogTraceFunction; + + std::string theme = m_roguelike_theme; + + std::vector combination = + RoguelikeCiphertextBoard.get_combination(m_roguelike_theme); + + std::string overview_str = + status()->get_str(Status::RoguelikeCiphertextBoardOverview).value_or(json::value().to_string()); + json::value overview_json = json::parse(overview_str).value_or(json::value()); + m_all_boards = overview_json.as_array(); + Log.debug(m_all_boards); + for (const auto& usage : combination) { + if (need_exit()) { + return false; + } + if (m_stage == usage.usage) { + // 用到没得用为止 + while (search_enable_pair(usage) && !need_exit()) { + Log.info("Use board pairs"); + } + break; + } + } + + return true; +} + +bool asst::RoguelikeCiphertextBoardUseTaskPlugin::search_enable_pair(const auto& usage) +{ + LogTraceFunction; + + for (const auto& pair : usage.pairs) { + // 遍历上板子 + for (const auto& up_board : pair.up_board) { + // 遍历下板子 + for (const auto& down_board : pair.down_board) { + if (board_pair(up_board, down_board)) return true; + } + } + } + + return false; +} + +bool asst::RoguelikeCiphertextBoardUseTaskPlugin::board_pair(const std::string& up_board, const std::string& down_board) +{ + LogTraceFunction; + + auto iter_up = std::find(m_all_boards.begin(), m_all_boards.end(), up_board); + auto iter_down = std::find(m_all_boards.begin(), m_all_boards.end(), down_board); + // 如果两个板子同时存在m_all_boards中 + if (iter_up != m_all_boards.end() && iter_down != m_all_boards.end()) { + if (use_board(up_board, down_board)) { + // 用完删除上板子和下板子 + m_all_boards.erase(iter_up); + iter_down = std::find(m_all_boards.begin(), m_all_boards.end(), down_board); + m_all_boards.erase(iter_down); + status()->set_str(Status::RoguelikeCiphertextBoardOverview, m_all_boards.to_string()); + Log.debug("Use board pairs"); + } + return true; + } + return false; +} + +bool asst::RoguelikeCiphertextBoardUseTaskPlugin::use_board(const std::string& up_board, const std::string& down_board) +{ + LogTraceFunction; + + if (ProcessTask(*this, { m_roguelike_theme + "@Roguelike@CiphertextBoard" }).run()) { + swipe_to_top(); + // todo:插入一个更新密文板overview + if (search_and_click_board(up_board)) { + search_and_click_board(down_board); + // 点击节点位置,todo:根据坐标换算位置 + if (m_stage == "Boss") { + // 滑到最右边,可能这里的逻辑需要扩充为找不到点就往右划,暂时先这么糊着,出现这种情况再写 + ProcessTask(*this, { "SwipeToTheLeft" }).run(); + } + ProcessTask(*this, { m_roguelike_theme + "@Roguelike@CiphertextBoardUseOnStage" }).run(); + if (ProcessTask(*this, { m_roguelike_theme + "@Roguelike@CiphertextBoardUseConfirm" }).run()) { + return true; + } + } + ProcessTask(*this, { m_roguelike_theme + "@Roguelike@CiphertextBoardBack" }).run(); + } + return false; +} + +bool asst::RoguelikeCiphertextBoardUseTaskPlugin::search_and_click_board(const std::string& board) +{ + LogTraceFunction; + + while (!need_exit()) { + OCRer analyzer(ctrler()->get_image()); + std::string task_name = m_roguelike_theme + "@Roguelike@CiphertextBoardUseOcr"; + analyzer.set_task_info(task_name); + analyzer.set_required({ board }); + if (!analyzer.analyze()) { + // 往上滑 + slowly_swipe(true); + } + else { + ctrler()->click(analyzer.get_result().front().rect.move(Task.get(task_name)->rect_move)); + return true; + } + } + return false; +} + +void asst::RoguelikeCiphertextBoardUseTaskPlugin::swipe_to_top() +{ + LogTraceFunction; + + // 找到布局"就到了最上面 + while (!need_exit()) { + OCRer analyzer(ctrler()->get_image()); + analyzer.set_task_info(m_roguelike_theme + "@Roguelike@CiphertextBoardUseOcr"); + if (analyzer.analyze()) { + return; + } + else { + // 往下滑 + ProcessTask(*this, { "RoguelikeCiphertextBoardSwipeToTheDown" }).run(); + } + } +} + +void asst::RoguelikeCiphertextBoardUseTaskPlugin::slowly_swipe(bool to_up, int swipe_dist) +{ + std::string swipe_task_name = + to_up ? "RoguelikeCiphertextBoardSlowlySwipeToTheUp" : "RoguelikeCiphertextBoardSwipeToTheDown"; + if (!ControlFeat::support(ctrler()->support_features(), + ControlFeat::PRECISE_SWIPE)) { // 不能精准滑动时不使用 swipe_dist 参数 + ProcessTask(*this, { swipe_task_name }).run(); + return; + } + + if (!to_up) swipe_dist = -swipe_dist; + auto swipe_task = Task.get(swipe_task_name); + const Rect& StartPoint = swipe_task->specific_rect; + ctrler()->swipe(StartPoint, + { StartPoint.x + swipe_dist - StartPoint.width, StartPoint.y, StartPoint.width, StartPoint.height }, + swipe_task->special_params.empty() ? 0 : swipe_task->special_params.at(0), + (swipe_task->special_params.size() < 2) ? false : swipe_task->special_params.at(1), + (swipe_task->special_params.size() < 3) ? 1 : swipe_task->special_params.at(2), + (swipe_task->special_params.size() < 4) ? 1 : swipe_task->special_params.at(3)); + sleep(swipe_task->post_delay); +} diff --git a/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.h new file mode 100644 index 0000000000..0a5098158b --- /dev/null +++ b/src/MaaCore/Task/Roguelike/RoguelikeCiphertextBoardUseTaskPlugin.h @@ -0,0 +1,36 @@ +#pragma once +#include "RoguelikeConfig.h" +#include "Task/AbstractTaskPlugin.h" + +namespace asst +{ + class RoguelikeCiphertextBoardUseTaskPlugin : public AbstractTaskPlugin, public RoguelikeConfig + { + public: + using AbstractTaskPlugin::AbstractTaskPlugin; + virtual ~RoguelikeCiphertextBoardUseTaskPlugin() override = default; + + public: + virtual bool verify(AsstMsg msg, const json::value& details) const override; + + protected: + virtual bool _run() override; + + private: + // 遍历配置里的组合 + bool search_enable_pair(const auto& usage); + // 查询是否有能使用的板子对 + bool board_pair(const std::string& up_board, const std::string& down_board); + // 使用板子对 + bool use_board(const std::string& up_board, const std::string& down_board); + // 找到并点击指定板子 + bool search_and_click_board(const std::string& board); + // 滑到最上面 + void swipe_to_top(); + // 往下滑 + void slowly_swipe(bool to_down, int swipe_dist = 200); + // 节点类型 + mutable std::string m_stage; + mutable json::array m_all_boards; + }; +} diff --git a/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp index eb067afddc..c05d1c875c 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp @@ -2,6 +2,7 @@ #include "Config/Miscellaneous/BattleDataConfig.h" #include "Config/Roguelike/RoguelikeShoppingConfig.h" +#include "Config/TaskData.h" #include "Controller/Controller.h" #include "Status.h" #include "Task/ProcessTask.h" @@ -104,6 +105,9 @@ bool asst::RoguelikeShoppingTaskPlugin::_run() bool bought = false; auto& all_goods = RoguelikeShopping.get_goods(m_roguelike_theme); + std::vector all_ciphertext_board = + m_roguelike_theme == "Sami" ? Task.get("Sami@Roguelike@CiphertextBoardGainOcr")->text + : std::vector(); for (const auto& goods : all_goods) { if (need_exit()) { return false; @@ -166,6 +170,19 @@ bool asst::RoguelikeShoppingTaskPlugin::_run() Log.info("Ready to buy", goods.name); ctrler()->click(find_it->rect); bought = true; + if (m_roguelike_theme == "Sami") { + + auto iter = std::find(all_ciphertext_board.begin(), all_ciphertext_board.end(), goods.name); + if (iter != all_ciphertext_board.end()) { + std::string overview_str = + status()->get_str(Status::RoguelikeCiphertextBoardOverview).value_or(json::value().to_string()); + + auto& overview = json::parse(overview_str).value_or(json::value()).as_array(); + // 把ciphertext_board存到overview里 + overview.push_back(goods.name); + status()->set_str(Status::RoguelikeCiphertextBoardOverview, overview.to_string()); + } + } if (goods.no_longer_buy) { status()->set_number(Status::RoguelikeTraderNoLongerBuy, 1); }