revert: 恢复萨米肉鸽使用密文板

Revert "Revert "feat: 萨米肉鸽使用密文板 (#6949)" (#7054)"

This reverts commit c109acd709.
This commit is contained in:
zzyyyl
2023-10-25 14:41:22 +08:00
parent 11b6f88a4e
commit c04f27c8ee
60 changed files with 1197 additions and 32 deletions

View File

@@ -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": "变为木裂前兆,只能和“伤痕”组合"
}
]
}
]
}

View File

@@ -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",

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -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

View File

@@ -0,0 +1,35 @@
#include "RoguelikeCiphertextBoardConfig.h"
#include <meojson/json.hpp>
#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;
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "Config/AbstractConfig.h"
#include <vector>
#include "Common/AsstBattleDef.h"
namespace asst
{
// 板子组合
struct CiphertextBoardPair
{
std::vector<std::string> up_board; // 上板子
std::vector<std::string> down_board; // 下板子
};
struct RoguelikeCiphertextBoardCombination
{
std::string usage; // 适用的节点类型和用法
std::vector<CiphertextBoardPair> pairs; // 适用的板子组合
};
class RoguelikeCiphertextBoardConfig final : public SingletonHolder<RoguelikeCiphertextBoardConfig>,
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<std::string, std::vector<RoguelikeCiphertextBoardCombination>>
m_ciphertext_board_combination;
};
inline static auto& RoguelikeCiphertextBoard = RoguelikeCiphertextBoardConfig::get_instance();
}

View File

@@ -48,12 +48,14 @@
<ClInclude Include="Config\Miscellaneous\OcrConfig.h" />
<ClInclude Include="Config\Miscellaneous\SSSCopilotConfig.h" />
<ClInclude Include="Config\OnnxSessions.h" />
<ClInclude Include="Config\Roguelike\RoguelikeCiphertextBoardConfig.h" />
<ClInclude Include="Controller\adb-lite\client.hpp" />
<ClInclude Include="Controller\adb-lite\protocol.hpp" />
<ClInclude Include="Controller\Controller.h" />
<ClInclude Include="Controller\ControllerAPI.h" />
<ClInclude Include="Controller\ControllerFactory.h" />
<ClInclude Include="Controller\ControlScaleProxy.h" />
<ClCompile Include="Config\Roguelike\RoguelikeCiphertextBoardConfig.cpp" />
<ClCompile Include="Controller\MaaThriftController.h" />
<ClInclude Include="Controller\MaatouchController.h" />
<ClInclude Include="Controller\MinitouchController.h" />
@@ -86,6 +88,8 @@
<ClInclude Include="Task\BattleHelper.h" />
<ClInclude Include="Task\Interface\SingleStepTask.h" />
<ClInclude Include="Task\Interface\SSSCopilotTask.h" />
<ClInclude Include="Task\Roguelike\RoguelikeCiphertextBoardGainTaskPlugin.h" />
<ClInclude Include="Task\Roguelike\RoguelikeCiphertextBoardUseTaskPlugin.h" />
<ClInclude Include="Task\Roguelike\RoguelikeConfig.h" />
<ClInclude Include="Task\Roguelike\RoguelikeDifficultySelectionTaskPlugin.h" />
<ClInclude Include="Task\Roguelike\RoguelikeLastRewardTaskPlugin.h" />
@@ -254,6 +258,8 @@
<ClCompile Include="Task\BattleHelper.cpp" />
<ClCompile Include="Task\Interface\SingleStepTask.cpp" />
<ClCompile Include="Task\Interface\SSSCopilotTask.cpp" />
<ClCompile Include="Task\Roguelike\RoguelikeCiphertextBoardGainTaskPlugin.cpp" />
<ClCompile Include="Task\Roguelike\RoguelikeCiphertextBoardUseTaskPlugin.cpp" />
<ClCompile Include="Task\Roguelike\RoguelikeConfig.cpp" />
<ClCompile Include="Task\Roguelike\RoguelikeDifficultySelectionTaskPlugin.cpp" />
<ClCompile Include="Task\Roguelike\RoguelikeLastRewardTaskPlugin.cpp" />

View File

@@ -216,6 +216,9 @@
<ClInclude Include="Config\TemplResource.h">
<Filter>Source\Resource</Filter>
</ClInclude>
<ClInclude Include="Config\Roguelike\RoguelikeCiphertextBoardConfig.h">
<Filter>Source\Resource\Roguelike</Filter>
</ClInclude>
<ClInclude Include="Config\Roguelike\RoguelikeCopilotConfig.h">
<Filter>Source\Resource\Roguelike</Filter>
</ClInclude>
@@ -441,6 +444,12 @@
<ClInclude Include="Task\Roguelike\RoguelikeBattleTaskPlugin.h">
<Filter>Source\Task\Roguelike</Filter>
</ClInclude>
<ClInclude Include="Task\Roguelike\RoguelikeCiphertextBoardGainTaskPlugin.h">
<Filter>Source\Task\Roguelike</Filter>
</ClInclude>
<ClInclude Include="Task\Roguelike\RoguelikeCiphertextBoardUseTaskPlugin.h">
<Filter>Source\Task\Roguelike</Filter>
</ClInclude>
<ClInclude Include="Task\Roguelike\RoguelikeConfig.h">
<Filter>Source\Task\Roguelike</Filter>
</ClInclude>
@@ -731,6 +740,9 @@
<ClCompile Include="Config\TemplResource.cpp">
<Filter>Source\Resource</Filter>
</ClCompile>
<ClCompile Include="Config\Roguelike\RoguelikeCiphertextBoardConfig.cpp">
<Filter>Source\Resource\Roguelike</Filter>
</ClCompile>
<ClCompile Include="Config\Roguelike\RoguelikeCopilotConfig.cpp">
<Filter>Source\Resource\Roguelike</Filter>
</ClCompile>
@@ -905,6 +917,12 @@
<ClCompile Include="Task\Roguelike\RoguelikeBattleTaskPlugin.cpp">
<Filter>Source\Task\Roguelike</Filter>
</ClCompile>
<ClCompile Include="Task\Roguelike\RoguelikeCiphertextBoardGainTaskPlugin.cpp">
<Filter>Source\Task\Roguelike</Filter>
</ClCompile>
<ClCompile Include="Task\Roguelike\RoguelikeCiphertextBoardUseTaskPlugin.cpp">
<Filter>Source\Task\Roguelike</Filter>
</ClCompile>
<ClCompile Include="Task\Roguelike\RoguelikeConfig.cpp">
<Filter>Source\Task\Roguelike</Filter>
</ClCompile>

View File

@@ -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:

View File

@@ -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<RoguelikeDifficultySelectionTaskPlugin>();
m_strategy_change_plugin_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeStrategyChangeTaskPlugin>();
m_ciphertext_board_gain_plugin_ptr =
m_roguelike_task_ptr->register_plugin<RoguelikeCiphertextBoardGainTaskPlugin>();
m_ciphertext_board_use_plugin_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeCiphertextBoardUseTaskPlugin>();
// 这个任务如果卡住会放弃当前的肉鸽并重新开始,所以多添加一点。先这样凑合用
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 - 刷经验,尽可能稳定地打更多层数,不期而遇采用激进策略

View File

@@ -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<RoguelikeShoppingTaskPlugin> m_shopping_plugin_ptr = nullptr;
std::shared_ptr<RoguelikeStageEncounterTaskPlugin> m_stage_encounter_plugin_ptr = nullptr;
std::shared_ptr<RoguelikeStrategyChangeTaskPlugin> m_strategy_change_plugin_ptr = nullptr;
std::shared_ptr<RoguelikeCiphertextBoardGainTaskPlugin> m_ciphertext_board_gain_plugin_ptr = nullptr;
std::shared_ptr<RoguelikeCiphertextBoardUseTaskPlugin> m_ciphertext_board_use_plugin_ptr = nullptr;
};
}

View File

@@ -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;
}

View File

@@ -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;
};
}

View File

@@ -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<RoguelikeCiphertextBoardCombination> 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);
}

View File

@@ -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;
};
}

View File

@@ -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<std::string> all_ciphertext_board =
m_roguelike_theme == "Sami" ? Task.get<OcrTaskInfo>("Sami@Roguelike@CiphertextBoardGainOcr")->text
: std::vector<std::string>();
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);
}