diff --git a/resource/roguelike/Sami/autopilot/事不过四_for_collapse.json b/resource/roguelike/Sami/autopilot/事不过四_for_collapse.json new file mode 100755 index 0000000000..6387d5810e --- /dev/null +++ b/resource/roguelike/Sami/autopilot/事不过四_for_collapse.json @@ -0,0 +1,79 @@ +{ + "stage_name": "事不过四_collapse", + "replacement_home": [ + { + "location": [ + 5, + 1 + ], + "direction": "left" + } + ], + "blacklist_location": [ + [ + 2, + 2 + ] + ], + "deploy_plan": [ + { + "groups": [ + "地面阻挡" + ], + "location": [ + 5, + 1 + ], + "direction": "left", + "condition": [ 1, 13 ] + }, + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 4, + 1 + ], + "direction": "left", + "condition": [ 1, 13 ] + }, + { + "groups": [ + "益达" + ], + "location": [ + 6, + 1 + ], + "direction": "left", + "condition": [ 1, 13 ] + }, + { + "groups": [ + "奶" + ], + "location": [ + 6, + 2 + ], + "direction": "left", + "condition": [ 1, 13 ] + }, + { + "groups": [ + "高台输出", + "辅助", + "其他高台" + ], + "location": [ + 7, + 1 + ], + "direction": "left", + "condition": [ 1, 13 ] + } + ] +} diff --git a/resource/roguelike/Sami/autopilot/半吊子之旅_for_collapse.json b/resource/roguelike/Sami/autopilot/半吊子之旅_for_collapse.json new file mode 100755 index 0000000000..6dbf28779f --- /dev/null +++ b/resource/roguelike/Sami/autopilot/半吊子之旅_for_collapse.json @@ -0,0 +1,142 @@ +{ + "stage_name": "半吊子之旅_collapse", + "replacement_home": [ + { + "location": [ + 5, + 3 + ], + "direction": "left" + }, + { + "location": [ + 5, + 4 + ], + "direction": "left" + }, + { + "location": [ + 5, + 2 + ], + "direction": "down" + }, + { + "location": [ + 5, + 5 + ], + "direction": "up" + } + ], + "blacklist_location": [ + [ + 6, + 3 + ], + [ + 6, + 4 + ], + [ + 4, + 3 + ], + [ + 4, + 4 + ] + ], + "deploy_plan": [ + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 5, + 3 + ], + "direction": "left", + "condition": [ 1, 14 ] + }, + { + "groups": [ + "益达" + ], + "location": [ + 8, + 3 + ], + "direction": "left", + "condition": [ 1, 14 ] + }, + { + "groups": [ + "回费", + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 5, + 4 + ], + "direction": "left", + "condition": [ 1, 14 ] + }, + { + "groups": [ + "高台输出", + "辅助", + "盾法", + "其他高台" + ], + "location": [ + 4, + 2 + ], + "direction": "down", + "condition": [ 1, 14 ] + }, + { + "groups": [ + "奶" + ], + "location": [ + 6, + 2 + ], + "direction": "down", + "condition": [ 1, 14 ] + }, + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 5, + 2 + ], + "direction": "down", + "condition": [ 1, 14 ] + }, + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 5, + 5 + ], + "direction": "up", + "condition": [ 1, 14 ] + } + ] +} \ No newline at end of file diff --git a/resource/roguelike/Sami/autopilot/度假村冤魂_for_collapse.json b/resource/roguelike/Sami/autopilot/度假村冤魂_for_collapse.json new file mode 100755 index 0000000000..ce9cc0a95c --- /dev/null +++ b/resource/roguelike/Sami/autopilot/度假村冤魂_for_collapse.json @@ -0,0 +1,157 @@ +{ + "stage_name": "度假村冤魂_collapse", + "replacement_home": [ + { + "location": [ + 2, + 3 + ], + "direction": "right" + }, + { + "location": [ + 0, + 3 + ], + "direction": "none" + } + ], + "deploy_plan": [ + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 2, + 3 + ], + "direction": "right", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "益达" + ], + "location": [ + 2, + 4 + ], + "direction": "up", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "奶" + ], + "location": [ + 1, + 4 + ], + "direction": "right", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "高台输出", + "辅助", + "群奶" + ], + "location": [ + 4, + 4 + ], + "direction": "left", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "地面远程", + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 1, + 3 + ], + "direction": "right", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "处决者", + "炮灰", + "其他地面" + ], + "location": [ + 7, + 2 + ], + "direction": "down", + "condition": [ + 1, + 10 + ] + }, + { + "groups": [ + "奶", + "高台输出", + "狙击", + "辅助", + "其他高台" + ], + "location": [ + 3, + 2 + ], + "direction": "down", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "奶", + "高台输出", + "狙击", + "辅助", + "其他高台" + ], + "location": [ + 4, + 2 + ], + "direction": "down", + "condition": [ 1, 32 ] + }, + { + "groups": [ + "处决者", + "炮灰", + "其他地面" + ], + "location": [ + 3, + 4 + ], + "direction": "up", + "condition": [ + 15, + 30 + ] + } + ], + "retreat_plan": [ + { + "location": [ + 7, + 2 + ], + "condition": [ + 10, + 15 + ] + } + ] +} diff --git a/resource/roguelike/Sami/autopilot/待宰的兽群_for_collapse.json b/resource/roguelike/Sami/autopilot/待宰的兽群_for_collapse.json new file mode 100755 index 0000000000..600e3ce2d2 --- /dev/null +++ b/resource/roguelike/Sami/autopilot/待宰的兽群_for_collapse.json @@ -0,0 +1,135 @@ +{ + "stage_name": "待宰的兽群_collapse", + "replacement_home": [ + { + "location": [ + 6, + 3 + ], + "direction": "left" + } + ], + "blacklist_location": [ + [ + 6, + 1 + ], + [ + 6, + 2 + ] + ], + "deploy_plan": [ + { + "groups": [ + "地面阻挡", + "其他地面" + ], + "location": [ + 6, + 3 + ], + "direction": "left", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "益达" + ], + "location": [ + 3, + 3 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "提丰" + ], + "location": [ + 3, + 2 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "水陈" + ], + "location": [ + 4, + 2 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "凯尔希", + "单奶", + "焰苇" + ], + "location": [ + 3, + 3 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "高台输出", + "辅助", + "其他高台" + ], + "location": [ + 4, + 2 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "高台输出", + "辅助", + "群奶", + "盾法", + "其他高台" + ], + "location": [ + 5, + 2 + ], + "direction": "down", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "地面阻挡", + "其他地面" + ], + "location": [ + 5, + 4 + ], + "direction": "up", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "高台输出", + "辅助", + "其他高台" + ], + "location": [ + 3, + 2 + ], + "direction": "down", + "condition": [ 1, 22 ] + } + ] +} diff --git a/resource/roguelike/Sami/autopilot/死囚之夜_for_collapse.json b/resource/roguelike/Sami/autopilot/死囚之夜_for_collapse.json new file mode 100755 index 0000000000..2edd847ad9 --- /dev/null +++ b/resource/roguelike/Sami/autopilot/死囚之夜_for_collapse.json @@ -0,0 +1,155 @@ +{ + "stage_name": "死囚之夜_collapse", + "replacement_home": [ + { + "location": [ + 4, + 3 + ], + "direction": "down" + } + ], + "blacklist_location": [ + [ + 3, + 1 + ], + [ + 2, + 2 + ], + [ + 5, + 1 + ] + ], + "deploy_plan": [ + { + "groups": [ + "地面阻挡", + "处决者" + ], + "location": [ + 3, + 4 + ], + "direction": "right", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "益达" + ], + "location": [ + 3, + 3 + ], + "direction": "down", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "焰苇", + "凯尔希", + "水陈", + "召唤" + ], + "location": [ + 3, + 2 + ], + "direction": "down", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "召唤", + "高台输出", + "盾法", + "辅助" + ], + "location": [ + 2, + 3 + ], + "direction": "down", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "奶" + ], + "location": [ + 5, + 3 + ], + "direction": "left", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "地面远程" + ], + "location": [ + 4, + 2 + ], + "direction": "down", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "地面阻挡", + "处决者" + ], + "location": [ + 4, + 5 + ], + "direction": "up", + "condition": [ 0, 13 ] + }, + { + "groups": [ + "地面阻挡", + "处决者" + ], + "location": [ + 3, + 5 + ], + "direction": "up", + "condition": [ 0, 13 ] + } + ], + "retreat_plan": [ + { + "location": [ 3, 3 ], + "condition": [ 14, 15 ] + }, + { + "location": [ 3, 4 ], + "condition": [ 14, 15 ] + }, + { + "location": [ 5, 3 ], + "condition": [ 14, 15 ] + }, + { + "location": [ 3, 2 ], + "condition": [ 13, 15 ] + }, + { + "location": [ 4, 2 ], + "condition": [ 13, 15 ] + }, + { + "location": [ 4, 5 ], + "condition": [ 13, 15 ] + }, + { + "location": [ 3, 5 ], + "condition": [ 13, 15 ] + } + ] +} diff --git a/resource/roguelike/Sami/autopilot/苔手_for_collapse.json b/resource/roguelike/Sami/autopilot/苔手_for_collapse.json new file mode 100755 index 0000000000..b785ed16dd --- /dev/null +++ b/resource/roguelike/Sami/autopilot/苔手_for_collapse.json @@ -0,0 +1,100 @@ +{ + "stage_name": "苔手_collapse", + "replacement_home": [ + { + "location": [ + 8, + 2 + ], + "direction": "left" + } + ], + "deploy_plan": [ + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 8, + 2 + ], + "direction": "left", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "地面阻挡", + "处决者", + "其他地面" + ], + "location": [ + 7, + 2 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "益达" + ], + "location": [ + 6, + 2 + ], + "direction": "down", + "condition": [ 2, 22 ] + }, + { + "groups": [ + "焰苇", + "凯尔希" + ], + "location": [ + 4, + 2 + ], + "direction": "right", + "condition": [ 2, 22 ] + }, + { + "groups": [ + "奶" + ], + "location": [ + 4, + 2 + ], + "direction": "right", + "condition": [ 1, 22 ] + }, + { + "groups": [ + "高台输出", + "盾法" + ], + "location": [ + 6, + 4 + ], + "direction": "up", + "condition": [ 2, 22 ] + }, + { + "groups": [ + "地面远程", + "玛恩纳", + "地面阻挡", + "其他地面" + ], + "location": [ + 8, + 2 + ], + "direction": "left", + "condition": [ 2, 22 ] + } + ] +} diff --git a/resource/roguelike/Sami/collapsal_paradigms.json b/resource/roguelike/Sami/collapsal_paradigms.json new file mode 100644 index 0000000000..c78add4cac --- /dev/null +++ b/resource/roguelike/Sami/collapsal_paradigms.json @@ -0,0 +1,56 @@ +{ + "theme": "Sami", + "collapsal_paradigms": [ + { + "level_1": "去量化", + "level_2" : "去量深化", + "rarity": "normal" + }, + { + "level_1": "实质性坍缩", + "level_2" : "蔓延性坍缩", + "rarity": "normal" + }, + { + "level_1": "非线性移动", + "level_2" : "非线性行动", + "rarity": "normal" + }, + { + "level_1": "情绪实体", + "level_2" : "恐怖实体", + "rarity": "normal" + }, + { + "level_1": "泛社会悖论", + "level_2" : "泛文明悖论", + "rarity": "normal" + }, + { + "level_1": "气压异常", + "level_2" : "气压失序", + "rarity": "normal" + }, + { + "level_1": "触发性损伤", + "level_2" : "触发性危殆", + "rarity": "normal" + }, + { + "level_1": "趋同性消耗", + "level_2" : "趋同性缺失", + "rarity": "normal" + }, + { + "level_1": "目空一些", + "level_2" : "睁眼瞎", + "rarity": "rare" + }, + { + "level_1": "图像损坏", + "level_2" : "一抹黑", + "rarity": "rare" + } + + ] +} \ No newline at end of file diff --git a/resource/roguelike/Sami/encounter_for_collapse.json b/resource/roguelike/Sami/encounter_for_collapse.json new file mode 100644 index 0000000000..205c983459 --- /dev/null +++ b/resource/roguelike/Sami/encounter_for_collapse.json @@ -0,0 +1,790 @@ +{ + "theme": "Sami_collapse", + "stage": [ + { + "name": "吉兆", + "option_num": 2, + "choose": 2 + }, + { + "name": "雨!", + "option_num": 2, + "choose": 1 + }, + { + "name": "随到随取", + "option_num": 2, + "choose": 2, + "choices": [ + { + "name": "使用热像仪", + "option_num": 2, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "3" + } + ] + } + ] + }, + { + "name": "定期维护", + "option_num": 2, + "choose": 1, + "note": "拥有【安玛的爱】时出现第三选项", + "choices": [ + { + "name": "检查多色测光望远镜的目镜", + "option_num": 2, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "4" + } + ] + }, + { + "name": "不紧不慢地打开一听罐头汤", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Relic", + "type": "have", + "value": "安玛的爱" + } + ] + } + ] + }, + { + "name": "昏黑之室", + "option_num": 3, + "choose": 1 + }, + { + "name": "疗愈仪式", + "option_num": 2, + "choose": 2 + }, + { + "name": "黑色足迹", + "option_num": 2, + "choose": 2, + "note": "抗干扰指数为0时出现第三选项,遭遇过【负伤的主树】事件时出现第四选项", + "choices": [ + { + "name": "逃离", + "option_num": 2, + "choose": 2, + "requirements": [ + { + "name": "LivePoint", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "解释情况", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": "=", + "value": "0" + } + ] + }, + { + "name": "解释情况", + "option_num": 4, + "choose": 4, + "requirements": [] + } + ] + }, + { + "name": "不冻河", + "option_num": 2, + "choose": 2, + "note": "拥有【安玛的爱】时出现第三选项", + "choices": [ + { + "name": "寻找工具", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Relic", + "type": "have", + "value": "安玛的爱" + } + ] + } + ] + }, + { + "name": "野外生存专家", + "option_num": 3, + "choose": 3, + "choices": [ + { + "name": "意思意思", + "option_num": 3, + "choose": 1, + "requirements": [ + { + "name": "OriginiumIngot", + "type": ">", + "value": "2" + } + ] + }, + { + "name": "重金酬谢", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "OriginiumIngot", + "type": ">", + "value": "4" + }, + { + "name": "Vision", + "type": ">", + "value": "2" + } + ] + } + ] + }, + { + "name": "在地公共信号放大站756号", + "option_num": 3, + "choose": 1, + "choices": [ + { + "name": "提供位置,呼叫增援", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "3" + } + ] + } + ] + }, + { + "name": "特里蒙旅行社特派团", + "option_num": 3, + "choose": 1 + }, + { + "name": "在地公共移动站N6号", + "option_num": 1, + "choose": 1, + "note": "拥有【安玛的爱】时出现第二选项,遭遇过【特里蒙旅行社特派团】事件且选择【拿走广告】时出现第三选项", + "choices": [ + { + "name": "“敲一敲”都能解决", + "option_num": 2, + "choose": 2, + "requirements": [ + { + "name": "Relic", + "type": "have", + "value": "安玛的爱" + } + ] + }, + { + "name": "寻找工具", + "option_num": 3, + "choose": 3, + "requirements": [] + } + ] + }, + { + "name": "度假胜地", + "option_num": 1, + "choose": 1 + }, + { + "name": "负伤的主树", + "option_num": 2, + "choose": 2 + }, + { + "name": "不见群山", + "option_num": 4, + "choose": 1, + "choices": [ + { + "name": "选择她弃在手边的塔罗牌", + "option_num": 4, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "3" + } + ] + } + ] + }, + { + "name": "远见所向", + "option_num": 4, + "choose": 1, + "choices": [ + { + "name": "我们或许能协作互助", + "option_num": 4, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "4" + } + ] + } + ] + }, + { + "name": "萨米之语", + "option_num": 1, + "choose": 1 + }, + { + "name": "乌萨斯", + "option_num": 3, + "choose": 1 + }, + { + "name": "无用之物", + "option_num": 3, + "choose": 2 + }, + { + "name": "沼泽里的抽泣声", + "option_num": 3, + "choose": 1 + }, + { + "name": "有利可图", + "option_num": 3, + "choose": 1 + }, + { + "name": "随行人员", + "option_num": 3, + "choose": 1 + }, + { + "name": "邪恶计划鸭", + "option_num": 2, + "choose": 2, + "choices": [ + { + "name": "你在做什么?", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "LivePoint", + "type": ">", + "value": "3" + } + ] + } + ] + }, + { + "name": "百里连营", + "option_num": 3, + "choose": 3, + "choices": [ + { + "name": "一边警戒一边前进", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "1" + } + ] + } + ] + }, + { + "name": "请君入戏", + "option_num": 3, + "choose": 1 + }, + { + "name": "北风女巫", + "option_num": 3, + "choose": 1, + "choices": [ + { + "name": "乖乖照做", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "5" + } + ] + } + ] + }, + { + "name": "时刻警惕", + "option_num": 2, + "choose": 2 + }, + { + "name": "猜疑链", + "option_num": 3, + "choose": 3, + "choices": [ + { + "name": "勘察情况并维持秩序", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "3" + } + ] + } + ] + }, + { + "name": "变化", + "option_num": 2, + "choose": 2 + }, + { + "name": "走过萨米的臂膀", + "option_num": 2, + "choose": 1, + "choices": [ + { + "name": "戴上头盔", + "option_num": 2, + "choose": 2, + "requirements": [ + { + "name": "Relic", + "type": "have", + "value": "树痕之盔" + } + ] + } + ] + }, + { + "name": "木裂前兆", + "option_num": 2, + "choose": 1 + }, + { + "name": "悲观者囚笼", + "option_num": 2, + "choose": 1 + }, + { + "name": "重构", + "option_num": 2, + "choose": 1, + "choices": [ + { + "name": "过载使用探测仪器", + "option_num": 2, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "依靠安玛的遗赠", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Relic", + "type": "have", + "value": "树痕之盔" + } + ] + } + ] + }, + { + "name": "探索者的一小步", + "option_num": 1, + "choose": 1 + }, + { + "name": "鲍勃杂货店", + "option_num": 3, + "choose": 1, + "choices": [ + { + "name": "选择他脚边的货品", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "1" + } + ] + }, + { + "name": "选择仓库深处的货品", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "选择仓库深处的货品", + "option_num": 4, + "choose": 4, + "requirements": [ + { + "name": "Relic", + "type": "have", + "value": "四叶草化石" + } + ] + } + ] + }, + { + "name": "科考站", + "option_num": 3, + "choose": 1 + }, + { + "name": "北地巫师竞技", + "option_num": 2, + "choose": 2 + }, + { + "name": "最好的朋友", + "option_num": 2, + "choose": 2 + }, + { + "name": "深渊入口", + "option_num": 2, + "choose": 2 + }, + { + "name": "低地市集", + "option_num": 3, + "choose": 3, + "choices": [ + { + "name": "选择碎草药", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "选择好看的织物", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "选择湿膏药", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "选择好看的木刻", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "选择纯霜露", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "选择琥珀核", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "帮助拿着密文版的萨米人", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Foldartal", + "type": "not have", + "value": "伤痕 && 空无" + } + ] + }, + { + "name": "循着嚎叫声走去", + "option_num": 4, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": "=", + "value": "5 || 6" + } + ] + }, + { + "name": "循着号角声走去", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "6" + } + ] + } + ] + }, + { + "name": "雪与木的笆篱", + "option_num": 3, + "choose": 3, + "choices": [ + { + "name": "“活力”", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "“金钱”", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "“树痕”", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Foldartal", + "type": "not have", + "value": "伤痕 && 空无" + } + ] + }, + { + "name": "“战斗”", + "option_num": 4, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": "=", + "value": "5 || 6" + } + ] + }, + { + "name": "“护卫”", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "6" + } + ] + } + ] + }, + { + "name": "安玛塔卢", + "option_num": 3, + "choose": 3, + "choices": [ + { + "name": "寻求希望", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "寻求护佑", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "ChaosLevel", + "type": ">", + "value": "3" + } + ] + }, + { + "name": "寻求“树痕”的踪迹", + "option_num": 3, + "choose": 2, + "requirements": [ + { + "name": "Foldartal", + "type": "not have", + "value": "伤痕 && 空无" + } + ] + }, + { + "name": "护卫林地", + "option_num": 4, + "choose": 4, + "requirements": [ + { + "name": "Vision", + "type": "=", + "value": "5 || 6" + } + ] + }, + { + "name": "坚守林地", + "option_num": 3, + "choose": 3, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "6" + } + ] + } + ] + }, + { + "name": "探寻前路", + "option_num": 3, + "choose": 2 + }, + { + "name": "前行的林地", + "option_num": 2, + "choose": 2, + "choices": [ + { + "name": "树上就不能走吗?", + "option_num": 2, + "choose": 1, + "requirements": [ + { + "name": "Vision", + "type": ">", + "value": "0" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/resource/roguelike/Sami/shopping.json b/resource/roguelike/Sami/shopping.json index c33726b74e..09387727b1 100644 --- a/resource/roguelike/Sami/shopping.json +++ b/resource/roguelike/Sami/shopping.json @@ -185,7 +185,8 @@ { "name": "警戒篱木", "effect": "坍缩值-2,目标生命上限+2", - "No": 198 + "No": 198, + "decrease_collapse": true }, { "name": "石像鬼塑像", @@ -402,7 +403,8 @@ { "name": "《重型音乐选集》", "effect": "坍缩值-2,希望+2", - "No": 199 + "No": 199, + "decrease_collapse": true }, { "name": "彩虹瓮", @@ -537,17 +539,20 @@ { "name": "万能钥匙-α", "effect": "【高寒化】希望+6,坍缩值-1", - "No": 10 + "No": 10, + "decrease_collapse": true }, { "name": "万能钥匙-β", "effect": "【冻土化】希望+7,坍缩值-1", - "No": 10 + "No": 10, + "decrease_collapse": true }, { "name": "万能钥匙-γ", "effect": "【极地化】希望+7,坍缩值-2", - "No": 10 + "No": 10, + "decrease_collapse": true }, { "name": "万能钥匙", @@ -1516,7 +1521,8 @@ { "name": "流浪术师的怀乡", "effect": "进入深埋迷境时,坍缩值-3", - "No": 200 + "No": 200, + "decrease_collapse": true }, { "name": "食腐者手杖", diff --git a/resource/tasks.json b/resource/tasks.json index 27dfa23ad1..6f6b18e3a8 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -13831,6 +13831,9 @@ "Roguelike@StrategyChange_mode4": { "baseTask": "Roguelike@StrategyChange_default" }, + "Roguelike@StrategyChange_mode5": { + "baseTask": "Roguelike@StrategyChange_default" + }, "Roguelike@TempRecruitFlag": { "action": "DoNothing", "roi": [ @@ -15249,6 +15252,109 @@ "Sami@Roguelike@Abandon" ] }, + "Sami@Roguelike@CheckCollapsalParadigms_onStage": { + "algorithm": "OcrDetect", + "action": "DoNothing", + "cache": false, + "text": [ + "初霜湖泽", + "密静林地", + "昧明冻土", + "积冰岩骸", + "无瑕花园", + "远见之构", + "深埋迷境" + ], + "roi": [ + 530, + 30, + 240, + 60 + ] + }, + "Sami@Roguelike@CheckCollapsalParadigms_loading": { + "algorithm": "OcrDetect", + "action": "DoNothing", + "cache": false, + "text": [ + "正在提交反馈至神经", + "正在提交反馈神经" + ], + "roi": [ + 700, + 640, + 270, + 50 + ] + }, + "Sami@Roguelike@CheckCollapsalParadigms_panel": { + "algorithm": "OcrDetect", + "action": "DoNothing", + "cache": false, + "text": [ + "去量化", + "去量深化", + "实质性坍缩", + "蔓延性坍缩", + "非线性移动", + "非线性行动", + "情绪实体", + "恐怖实体", + "泛社会悖论", + "泛文明悖论", + "气压异常", + "气压失序", + "触发性损伤", + "触发性危殆", + "趋同性消耗", + "趋同性缺失", + "目空一些", + "睁眼瞎", + "图像损坏", + "一抹黑" + ], + "roi": [ + 350, + 120, + 300, + 520 + ] + }, + "Sami@Roguelike@CheckCollapsalParadigms_banner": { + "algorithm": "OcrDetect", + "action": "DoNothing", + "cache": false, + "text": [ + "坍缩范式加深", + "坍缩范式消退", + "去量化", + "去量深化", + "实质性坍缩", + "蔓延性坍缩", + "非线性移动", + "非线性行动", + "情绪实体", + "恐怖实体", + "泛社会悖论", + "泛文明悖论", + "气压异常", + "气压失序", + "触发性损伤", + "触发性危殆", + "趋同性消耗", + "趋同性缺失", + "目空一些", + "睁眼瞎", + "图像损坏", + "一抹黑" + ], + "roi": [ + 945, + 60, + 335, + 660 + ] + }, "Sami@Roguelike@Foldartal": { "cache": false, "action": "ClickSelf", @@ -16456,6 +16562,51 @@ "Sami@Roguelike@CloseCollectionClose" ] }, + "Sami@Roguelike@Stages_collapsal_paradigms": { + "Doc": "为了刷隐藏坍缩而优先作战", + "algorithm": "JustReturn", + "next": [ + "Sami@Roguelike@NextLevel", + "Sami@Roguelike@StageCombatDps", + "Sami@Roguelike@StageCombatDpsAI6", + "Sami@Roguelike@StageVerticalCombatDps", + "Sami@Roguelike@StageVerticalCombatDpsAI6", + "Sami@Roguelike@StageFerociousPresage", + "Sami@Roguelike@StageEncounter", + "Sami@Roguelike@StageEncounterAI6", + "Sami@Roguelike@StageMysteriousPresage", + "Sami@Roguelike@StageTrader", + "Sami@Roguelike@StageTraderAI6", + "Sami@Roguelike@StageEmergencyDps", + "Sami@Roguelike@StageEmergencyDpsAI6", + "Sami@Roguelike@StageVerticalEmergencyDps", + "Sami@Roguelike@StageVerticalEmergencyDpsAI6", + "Sami@Roguelike@StageSafeHouse", + "Sami@Roguelike@StageSafeHouseAI6", + "Sami@Roguelike@StageBoons", + "Sami@Roguelike@StageBoonsAI6", + "Sami@Roguelike@StageVerticalSafeHouse", + "Sami@Roguelike@StageVerticalSafeHouseAI6", + "Sami@Roguelike@StageVerticalBoons", + "Sami@Roguelike@StageVerticalBoonsAI6", + "Sami@Roguelike@StageVerticalTrader", + "Sami@Roguelike@StageVerticalTraderAI6", + "Sami@Roguelike@StageWindAndRain", + "Sami@Roguelike@StageWindAndRainAI6", + "Sami@Roguelike@StageProphecy", + "Sami@Roguelike@StageProphecyAI6", + "Sami@Roguelike@StageBoskyPassage", + "Sami@Roguelike@StageBoskyPassageAI6", + "Sami@Roguelike@StageEmergencyTransportation", + "Sami@Roguelike@StageEmergencyTransportationAI6", + "Sami@Roguelike@StageGambling", + "Sami@Roguelike@StageGamblingAI6", + "Sami@Roguelike@StageDreadfulFoe", + "Sami@Roguelike@StageDreadfulFoe-5", + "Sami@Roguelike@CloseCollectionClose", + "Sami@Roguelike@Abandon" + ] + }, "Sami@Roguelike@StartExplore": { "roi": [ 958, @@ -16545,6 +16696,41 @@ ] ] }, + "Sami@Roguelike@StrategyChange_mode5": { + "text": [ + "_collapsal_paradigms" + ], + "ocrReplace": [ + [ + "初霜湖泽", + "_collapsal_paradigms" + ], + [ + "密静林地", + "_collapsal_paradigms" + ], + [ + "昧明冻土", + "_SKIP_" + ], + [ + "积冰岩骸", + "_SKIP_" + ], + [ + "无瑕花园", + "_SKIP_" + ], + [ + "远见之构", + "_SKIP_" + ], + [ + "深埋迷境", + "_SKIP_" + ] + ] + }, "Sami@Roguelike@TodoEnter": {}, "Sami@Roguelike@TraderCheck": { "algorithm": "MatchTemplate", diff --git a/src/MaaCore/Config/ResourceLoader.cpp b/src/MaaCore/Config/ResourceLoader.cpp index 54eb915c18..2627295bdc 100644 --- a/src/MaaCore/Config/ResourceLoader.cpp +++ b/src/MaaCore/Config/ResourceLoader.cpp @@ -17,6 +17,7 @@ #include "OnnxSessions.h" #include "Roguelike/RoguelikeCopilotConfig.h" #include "Roguelike/RoguelikeFoldartalConfig.h" +#include "Roguelike/RoguelikeCollapsalParadigmConfig.h" #include "Roguelike/RoguelikeRecruitConfig.h" #include "Roguelike/RoguelikeShoppingConfig.h" #include "Roguelike/RoguelikeStageEncounterConfig.h" @@ -206,11 +207,18 @@ bool asst::ResourceLoader::load(const std::filesystem::path& path) LoadResourceAndCheckRet( RoguelikeStageEncounterConfig, "roguelike"_p / "Sami"_p / "encounter_for_deposit.json"_p); + LoadResourceAndCheckRet( + RoguelikeStageEncounterConfig, + "roguelike"_p / "Sami"_p / "encounter_for_collapse.json"_p); LoadResourceAndCheckRet( RoguelikeFoldartalConfig, "roguelike"_p / "Sami"_p / "foldartal.json"_p); + LoadResourceAndCheckRet( + RoguelikeCollapsalParadigmConfig, + "roguelike"_p / "Sami"_p / "collapsal_paradigms.json"_p); + #undef LoadTemplByConfigAndCheckRet #undef LoadResourceAndCheckRet #undef LoadCacheWithoutRet diff --git a/src/MaaCore/Config/Roguelike/RoguelikeCollapsalParadigmConfig.cpp b/src/MaaCore/Config/Roguelike/RoguelikeCollapsalParadigmConfig.cpp new file mode 100644 index 0000000000..1fe6c35a31 --- /dev/null +++ b/src/MaaCore/Config/Roguelike/RoguelikeCollapsalParadigmConfig.cpp @@ -0,0 +1,44 @@ +#include "RoguelikeCollapsalParadigmConfig.h" + +#include + +#include "Utils/Logger.hpp" + +bool asst::RoguelikeCollapsalParadigmConfig::parse(const json::value& json) +{ + LogTraceFunction; + + const std::string theme = json.at("theme").as_string(); + m_clp_pd_classes.erase(theme); + m_clp_pd_dict.erase(theme); + m_rare_clp_pds.erase(theme); + + const auto& theme_json = json.at("collapsal_paradigms"); + unsigned int index = 0; + for (const auto& clp_pd_class_json : theme_json.as_array()) { + CollapsalParadigmClass clp_pd_class; + clp_pd_class.level_1 = clp_pd_class_json.at("level_1").as_string(); + clp_pd_class.level_2 = clp_pd_class_json.at("level_2").as_string(); + clp_pd_class.rarity = clp_pd_class_json.at("rarity").as_string(); + + m_clp_pd_dict[theme][clp_pd_class.level_1] = index; + m_clp_pd_dict[theme][clp_pd_class.level_2] = index; + + if (clp_pd_class.rarity == "rare") { + m_rare_clp_pds[theme].insert(clp_pd_class.level_1); + m_rare_clp_pds[theme].insert(clp_pd_class.level_2); + } + + m_clp_pd_classes[theme].emplace_back(std::move(clp_pd_class)); + + index++; + } + return true; +} + +void asst::RoguelikeCollapsalParadigmConfig::clear() +{ + m_clp_pd_classes.clear(); + m_clp_pd_dict.clear(); + m_rare_clp_pds.clear(); +} diff --git a/src/MaaCore/Config/Roguelike/RoguelikeCollapsalParadigmConfig.h b/src/MaaCore/Config/Roguelike/RoguelikeCollapsalParadigmConfig.h new file mode 100644 index 0000000000..3a3698149e --- /dev/null +++ b/src/MaaCore/Config/Roguelike/RoguelikeCollapsalParadigmConfig.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Config/AbstractConfig.h" + +#include + +#include "Common/AsstBattleDef.h" + +namespace asst +{ + // 坍缩范式 + struct CollapsalParadigmClass + { + std::string level_1; // 一级范式 + std::string level_2; // 二级范式 + std::string rarity; // 稀有度 + }; + + class RoguelikeCollapsalParadigmConfig final : public SingletonHolder, public AbstractConfig + { + public: + virtual ~RoguelikeCollapsalParadigmConfig() override = default; + + const auto& get_clp_pd_classes(const std::string& theme) const noexcept { return m_clp_pd_classes.at(theme); } + const auto& get_clp_pd_dict(const std::string& theme) const noexcept { return m_clp_pd_dict.at(theme); } + const auto& get_rare_clp_pds(const std::string& theme) const noexcept { return m_rare_clp_pds.at(theme); } + + private: + virtual bool parse(const json::value& json) override; + + void clear(); + + std::unordered_map> m_clp_pd_classes; + std::unordered_map> m_clp_pd_dict; + std::unordered_map> m_rare_clp_pds; + }; + + inline static auto& RoguelikeCollapsalParadigms = RoguelikeCollapsalParadigmConfig::get_instance(); +} diff --git a/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.cpp b/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.cpp index 172de7e542..607f1cb411 100644 --- a/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.cpp +++ b/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.cpp @@ -41,6 +41,7 @@ bool asst::RoguelikeShoppingConfig::parse(const json::value& json) goods.promotion = goods_json.get("promotion", 0); goods.no_longer_buy = goods_json.get("no_longer_buy", false); goods.ignore_no_longer_buy = goods_json.get("ignore_no_longer_buy", false); + goods.decrease_collapse = goods_json.get("decrease_collapse", false); m_goods[theme].emplace_back(std::move(goods)); } diff --git a/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.h b/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.h index 6756aab9ba..bbb9885889 100644 --- a/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.h +++ b/src/MaaCore/Config/Roguelike/RoguelikeShoppingConfig.h @@ -16,6 +16,7 @@ namespace asst int promotion = 0; // 晋升 N 个干员 bool no_longer_buy = false; bool ignore_no_longer_buy = false; + bool decrease_collapse = false; }; class RoguelikeShoppingConfig final : public SingletonHolder, public AbstractConfig diff --git a/src/MaaCore/MaaCore.vcxproj b/src/MaaCore/MaaCore.vcxproj index c3f7cb6ff0..7fba28b690 100644 --- a/src/MaaCore/MaaCore.vcxproj +++ b/src/MaaCore/MaaCore.vcxproj @@ -155,6 +155,7 @@ + @@ -208,6 +209,7 @@ + @@ -331,6 +333,7 @@ + @@ -383,6 +386,7 @@ + diff --git a/src/MaaCore/MaaCore.vcxproj.filters b/src/MaaCore/MaaCore.vcxproj.filters index d113d60c06..b2fac91c33 100644 --- a/src/MaaCore/MaaCore.vcxproj.filters +++ b/src/MaaCore/MaaCore.vcxproj.filters @@ -234,6 +234,9 @@ Source\Resource\Roguelike + + Source\Resource\Roguelike + Source\Resource\Miscellaneous @@ -495,6 +498,9 @@ Source\Task\Roguelike + + Source\Task\Roguelike + Source @@ -791,6 +797,9 @@ Source\Resource\Roguelike + + Source\Resource\Roguelike + Source\Resource\Miscellaneous @@ -998,6 +1007,9 @@ Source\Task\Roguelike + + Source\Task\Roguelike + Source diff --git a/src/MaaCore/Task/Interface/RoguelikeTask.cpp b/src/MaaCore/Task/Interface/RoguelikeTask.cpp index 352b041735..92cc2f681f 100644 --- a/src/MaaCore/Task/Interface/RoguelikeTask.cpp +++ b/src/MaaCore/Task/Interface/RoguelikeTask.cpp @@ -25,6 +25,9 @@ #include "Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h" #include "Task/Roguelike/RoguelikeStrategyChangeTaskPlugin.h" +#include "Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.h" +#include "Config/Roguelike/RoguelikeCollapsalParadigmConfig.h" + #include "Utils/Logger.hpp" asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, Assistant* inst) @@ -69,6 +72,8 @@ asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, Assistant* inst m_roguelike_task_ptr->register_plugin(m_roguelike_config_ptr); m_roguelike_task_ptr->register_plugin(m_roguelike_config_ptr); + m_roguelike_task_ptr->register_plugin(m_roguelike_config_ptr); + // 这个任务如果卡住会放弃当前的肉鸽并重新开始,所以多添加亿点。先这样凑合用 for (int i = 0; i != 999; ++i) { m_subtasks.emplace_back(m_roguelike_task_ptr); @@ -87,7 +92,7 @@ bool asst::RoguelikeTask::set_params(const json::value& params) } auto mode = static_cast(params.get("mode", 0)); - if (!RoguelikeConfig::is_valid_mode(mode)) { + if (!RoguelikeConfig::is_valid_mode(mode, theme)) { m_roguelike_task_ptr->set_tasks({ "Stop" }); Log.error(__FUNCTION__, "| Unknown mode", static_cast(mode)); return false; @@ -121,8 +126,15 @@ bool asst::RoguelikeTask::set_params(const json::value& params) m_roguelike_config_ptr->set_start_foldartal_list(std::move(list)); } - // 是否使用密文版 - m_roguelike_config_ptr->set_use_foldartal(params.get("use_foldartal", true)); + // 是否使用密文版, 非CLP_PDS模式下默认为True, CLP_PDS模式下默认为False + m_roguelike_config_ptr->set_use_foldartal(params.get("use_foldartal", !(mode == RoguelikeMode::CLP_PDS))); + + // 是否检查坍缩范式,非CLP_PDS模式下默认为False, CLP_PDS模式下默认为True + m_roguelike_config_ptr->set_check_clp_pds(params.get("check_collapsal_paradigms", mode == RoguelikeMode::CLP_PDS)); + m_roguelike_config_ptr->set_double_check_clp_pds(params.get("double_check_collapsal_paradigms", mode == RoguelikeMode::CLP_PDS)); + + const std::unordered_set& rare_clp_pds = RoguelikeCollapsalParadigms.get_rare_clp_pds(theme); + m_roguelike_config_ptr->set_expected_clp_pds(params.get("expected_collapsal_paradigms", rare_clp_pds)); m_roguelike_config_ptr->set_invest_maximum(params.get("investments_count", INT_MAX)); m_roguelike_config_ptr->set_invest_stop_when_full(params.get("stop_when_investment_full", false)); diff --git a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp index f4eaa30749..1edc1639c7 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp @@ -180,7 +180,16 @@ bool asst::RoguelikeBattleTaskPlugin::calc_stage_info() return false; } - auto opt = RoguelikeCopilot.get_stage_data(m_stage_name); + std::optional opt; + if (m_config->get_mode() == RoguelikeMode::CLP_PDS) { + opt = RoguelikeCopilot.get_stage_data(m_stage_name + "_collapse"); + if (opt == std::nullopt) { + opt = RoguelikeCopilot.get_stage_data(m_stage_name); + } + } else { + opt = RoguelikeCopilot.get_stage_data(m_stage_name); + } + if (opt) { m_homes = opt->replacement_home; m_allow_to_use_dice = opt->use_dice_stage; diff --git a/src/MaaCore/Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.cpp new file mode 100644 index 0000000000..88af218ba0 --- /dev/null +++ b/src/MaaCore/Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.cpp @@ -0,0 +1,342 @@ +#include "RoguelikeCollapsalParadigmTaskPlugin.h" +#include "Config/Roguelike/RoguelikeCollapsalParadigmConfig.h" + +#include "Config/TaskData.h" +#include "Controller/Controller.h" +#include "Task/ProcessTask.h" +#include "Utils/Logger.hpp" +#include "Vision/OCRer.h" + +#include + +#define DEBUG false + +bool asst::RoguelikeCollapsalParadigmTaskPlugin::verify(const AsstMsg msg, const json::value& details) const +{ + if ((msg != AsstMsg::SubTaskStart && msg != AsstMsg::SubTaskCompleted) || details.get("subtask", std::string()) != "ProcessTask") { + return false; + } + + if (!RoguelikeConfig::is_valid_theme(m_config->get_theme())) { + Log.error("Roguelike name doesn't exist!"); + return false; + } + + if (m_config->get_theme() != RoguelikeTheme::Sami || !m_config->get_check_clp_pds()) { + return false; + } + + const auto task_name = details.get("details", "task", ""); + + if (msg == AsstMsg::SubTaskStart && m_banner_triggers_start.find(task_name) != m_banner_triggers_start.end()) { + m_check_banner = true; + return true; + } + + if (msg == AsstMsg::SubTaskCompleted && m_banner_triggers_completed.find(task_name) != m_banner_triggers_completed.end()) { + m_check_banner = true; + return true; + } + + if(msg == AsstMsg::SubTaskStart && m_panel_triggers.find(task_name) != m_panel_triggers.end()) { + if (new_level()) { + m_need_check_panel = true; + m_verification_check = false; + } + + if (m_need_check_panel) { + m_need_check_panel = false; + m_check_panel = true; + return true; + } + } + + if (!m_need_check_panel && m_config->get_double_check_clp_pds() && msg == AsstMsg::SubTaskCompleted + && m_panel_triggers.find(task_name) == m_panel_triggers.end()) { + m_need_check_panel = true; + m_verification_check = true; + }; + + return false; +} + +bool asst::RoguelikeCollapsalParadigmTaskPlugin::_run() +{ + if (m_check_banner) { + if (DEBUG) { clp_pd_callback("坍缩范式Banner识别", 0, "CollapsalParadigmInfo"); } + m_check_banner = false; + return check_collapsal_paradigm_banner(); + } + if (m_check_panel) { + if (DEBUG) { clp_pd_callback(std::string("坍缩范式Panel") + (m_verification_check ? "验证" : "识别"), 0, "CollapsalParadigmInfo"); } + m_check_panel = false; + return check_collapsal_paradigm_panel(); + } + return false; +} + +bool asst::RoguelikeCollapsalParadigmTaskPlugin::check_collapsal_paradigm_banner() +{ + const std::string& theme = m_config->get_theme(); + + wait_for_loading(200); + + OCRer analyzer(ctrler()->get_image()); + if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + analyzer.set_task_info(theme + "@Roguelike@CheckCollapsalParadigms_banner"); + auto detected = analyzer.analyze(); + if (!detected) { // 以防万一,再识别一次 + wait_for_loading(200); + analyzer.set_image(ctrler()->get_image()); + if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + detected = analyzer.analyze(); + } + if (detected) { + const std::vector& clp_pd_classes = RoguelikeCollapsalParadigms.get_clp_pd_classes(theme); + const std::unordered_map& clp_pd_dict = RoguelikeCollapsalParadigms.get_clp_pd_dict(theme); + const std::unordered_set& expected_clp_pds = m_config->get_expected_clp_pds(); + std::vector prev_clp_pds = m_config->get_clp_pds(); + + std::string_view deepen_text = (Task.get(theme + "@Roguelike@CheckCollapsalParadigms_banner")->text)[0]; // "坍缩范式加深" + std::string_view weaken_text = (Task.get(theme + "@Roguelike@CheckCollapsalParadigms_banner")->text)[1]; // "坍缩范式消退" + + int banner_y = 0; + int deepen_or_weaken = 0; // 1 = deepen; 0 = unknown; -1 = weaken; + std::string cur_clp_pd; + std::vector::iterator it; + + OCRer::ResultsVec ocr_results = analyzer.get_result(); + std::sort(ocr_results.begin(), ocr_results.end(), + [](const OCRer::Result& x1, const OCRer::Result& x2){ return x1.rect.y < x2.rect.y; }); + for (const OCRer::Result& result : ocr_results) { + if (!deepen_or_weaken) { + if (result.text != deepen_text && result.text != weaken_text) { + clp_pd_callback("坍缩范式Banner识别错误" , 0, "CollapsalParadigmError"); + continue; + } + if (result.text == deepen_text) { + deepen_or_weaken = 1; + } + else { + deepen_or_weaken = -1; + } + banner_y = result.rect.y + result.rect.height; + } else { + if (result.text == deepen_text || result.text == weaken_text + || result.rect.y >= banner_y + 25) { + clp_pd_callback("坍缩范式Banner识别错误" , 0, "CollapsalParadigmError"); + continue; + } + cur_clp_pd = result.text; + const CollapsalParadigmClass& cur_class = clp_pd_classes.at(clp_pd_dict.at(cur_clp_pd)); + if (deepen_or_weaken == 1) { + it = std::find(prev_clp_pds.begin(), prev_clp_pds.end(), cur_clp_pd); + if (it == prev_clp_pds.end()) { + if (cur_clp_pd == cur_class.level_2) { + it = std::find(prev_clp_pds.begin(), prev_clp_pds.end(), cur_class.level_1); + if (it != prev_clp_pds.end()) { + clp_pd_callback(cur_clp_pd, 1, *it); + *it = cur_clp_pd; + } + else { + clp_pd_callback(cur_clp_pd, 1); + prev_clp_pds.emplace_back(cur_clp_pd); + } + } else { + clp_pd_callback(cur_clp_pd, 1); + prev_clp_pds.emplace_back(cur_clp_pd); + } + // check whether cur_clp_pd is an expected collapsal paradigm + // 判断 cur_clp_pd 是否为需要的坍缩范式 + if (expected_clp_pds.find(cur_clp_pd) != expected_clp_pds.end()) { + exit_then_stop(); + return true; + } else if (m_config->get_mode() == RoguelikeMode::CLP_PDS) { // 刷坍缩范式模式下,获得了不想要的坍缩范式 + exit_then_restart(); + return true; + } + } else { + clp_pd_callback("坍缩范式Banner识别重复" , 0, "CollapsalParadigmInfo"); + } + } else { + it = std::find(prev_clp_pds.begin(), prev_clp_pds.end(), cur_clp_pd); + if (it != prev_clp_pds.end()) { + if (cur_clp_pd == cur_class.level_2) { + clp_pd_callback(cur_class.level_1, -1, cur_clp_pd); + *it = cur_class.level_1; + // 如果2级直接消退到0级的话会有几次提示?这里可能会出问题,谨慎一些,再检查一次。 + m_need_check_panel = true; + } + else { + clp_pd_callback("", -1, cur_clp_pd); + prev_clp_pds.erase(it); + } + } + else { + clp_pd_callback("坍缩范式Banner识别重复" , 0, "CollapsalParadigmInfo"); + } + } + deepen_or_weaken = 0; + } + } + m_config->set_clp_pds(std::move(prev_clp_pds)); + } + return true; +} + +bool asst::RoguelikeCollapsalParadigmTaskPlugin::check_collapsal_paradigm_panel() +{ + const std::string& theme = m_config->get_theme(); + + const std::vector& clp_pd_classes = RoguelikeCollapsalParadigms.get_clp_pd_classes(theme); + const std::unordered_map& clp_pd_dict = RoguelikeCollapsalParadigms.get_clp_pd_dict(theme); + const std::unordered_set& expected_clp_pds = m_config->get_expected_clp_pds(); + std::vector prev_clp_pds = m_config->get_clp_pds(); + std::vector::iterator it = prev_clp_pds.begin(); + + wait_for_stage(200); + toggle_collapsal_status_panel(); + + OCRer analyzer(ctrler()->get_image()); + if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + analyzer.set_task_info(theme + "@Roguelike@CheckCollapsalParadigms_panel"); + OCRer::ResultsVec ocr_results = analyzer.analyze() ? analyzer.get_result() : OCRer::ResultsVec{}; + // 识别到三个及以上坍缩范式的时候,向上滑动一下再识别一次 + // if detect more than three collapsal paradigms, swipe up and analyze again + if (ocr_results.size() >= 3) { + ctrler()->swipe(m_swipe_begin, m_swipe_end, 500); + sleep(500); + analyzer.set_image(ctrler()->get_image()); + if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + if (analyzer.analyze()) { + ocr_results = analyzer.get_result(); + } + } + + std::sort(ocr_results.begin(), ocr_results.end(), + [](const OCRer::Result& x1, const OCRer::Result& x2){ return x1.rect.y < x2.rect.y; }); + + std::vector cur_clp_pds; + std::transform(ocr_results.begin(), ocr_results.end(), + std::back_inserter(cur_clp_pds), + [](OCRer::Result x) { return x.text; }); + + if (m_verification_check && prev_clp_pds != cur_clp_pds) { + clp_pd_callback("Collapsal Paradigm Verification Failed", 0, "CollapsalParadigmError"); + } + + for (const std::string& cur_clp_pd : cur_clp_pds) { + // 判断坍缩范式变动 + const unsigned int& cur_index = clp_pd_dict.at(cur_clp_pd); + const CollapsalParadigmClass& cur_class = clp_pd_classes.at(cur_index); + while (it != prev_clp_pds.end() && clp_pd_dict.at(*it) != cur_index) { + clp_pd_callback("", -1, *it); + ++it; + } + if (it == prev_clp_pds.end()) { // 全新的坍缩范式 + if (m_verification_check) { + clp_pd_callback("Miss Collapsal Paradigm: " + cur_clp_pd, 0, "CollapsalParadigmError"); + } + clp_pd_callback(cur_clp_pd, 1); + } else { + if (cur_clp_pd == cur_class.level_2 && *it == cur_class.level_1) { // 从1级加深到2级 + clp_pd_callback(cur_clp_pd, 1, cur_class.level_1); + + } else if (cur_clp_pd == cur_class.level_1 && *it == cur_class.level_2) { // 从2级消退到1级 + clp_pd_callback(cur_clp_pd, -1, cur_class.level_2); + } + ++it; + } + // 判断 cur_clp_pd 是否为需要的坍缩范式 + // check whether cur_clp_pd is an expected collapsal paradigm + if (expected_clp_pds.find(cur_clp_pd) != expected_clp_pds.end()) { + toggle_collapsal_status_panel(); + exit_then_stop(); + return true; + } + else if (m_config->get_mode() == RoguelikeMode::CLP_PDS) { // 刷坍缩范式模式下,获得了不想要的坍缩范式 + toggle_collapsal_status_panel(); + exit_then_restart(); + return true; + } + } + while (it != prev_clp_pds.end()) { + clp_pd_callback("", -1, *it); + ++it; + } + + m_config->set_clp_pds(std::move(cur_clp_pds)); + + toggle_collapsal_status_panel(); + + return true; +} + +void asst::RoguelikeCollapsalParadigmTaskPlugin::exit_then_stop() +{ + ProcessTask(*this, { m_config->get_theme() + "@Roguelike@ExitThenAbandon" }) + .set_times_limit(m_config->get_theme() + "@Roguelike@Abandon", 0) + .run(); + m_task_ptr->set_enable(false); +} + +void asst::RoguelikeCollapsalParadigmTaskPlugin::exit_then_restart() +{ + ProcessTask(*this, { m_config->get_theme() + "@Roguelike@ExitThenAbandon" }) + .set_times_limit("Roguelike@Abandon", 0) + .run(); +} + +void asst::RoguelikeCollapsalParadigmTaskPlugin::clp_pd_callback(std::string cur, int deepen_or_weaken, std::string prev) { + callback(AsstMsg::SubTaskExtraInfo, json::object { + { "what", "RoguelikeCollapsalParadigms" }, + { "details", json::object { + { "cur", cur }, + { "deepen_or_weaken", deepen_or_weaken }, + { "prev", prev } + } } + }); +} + +void asst::RoguelikeCollapsalParadigmTaskPlugin::toggle_collapsal_status_panel() +{ + ctrler()->click(m_roi); // 点击屏幕上方居中区域以开始检查坍缩状态 + sleep(500); +} + +void asst::RoguelikeCollapsalParadigmTaskPlugin::wait_for_loading(unsigned int millisecond) { + OCRer analyzer(ctrler()->get_image()); + // if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + analyzer.set_task_info(m_config->get_theme() + "@Roguelike@CheckCollapsalParadigms_loading"); + while (analyzer.analyze()) { + sleep(100); + analyzer.set_image(ctrler()->get_image()); + // if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + } + sleep(millisecond); +} + +void asst::RoguelikeCollapsalParadigmTaskPlugin::wait_for_stage(unsigned int millisecond) { + OCRer analyzer(ctrler()->get_image()); + // if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + analyzer.set_task_info(m_config->get_theme() + "@Roguelike@CheckCollapsalParadigms_onStage"); + while (!analyzer.analyze()) { + sleep(100); + analyzer.set_image(ctrler()->get_image()); + // if (DEBUG) { analyzer.save_img(utils::path("debug") / utils::path("collapsalParadigms")); } + } + sleep(millisecond); +} + +bool asst::RoguelikeCollapsalParadigmTaskPlugin::new_level() const { + OCRer analyzer(ctrler()->get_image()); + analyzer.set_task_info(m_config->get_theme() + "@Roguelike@CheckCollapsalParadigms_onStage"); + if (analyzer.analyze()) { + std::string level = analyzer.get_result().front().text; + if (level != m_level) { + m_level = level; + return true; + } + } + return false; +} diff --git a/src/MaaCore/Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.h new file mode 100644 index 0000000000..5e081d076d --- /dev/null +++ b/src/MaaCore/Task/Roguelike/RoguelikeCollapsalParadigmTaskPlugin.h @@ -0,0 +1,123 @@ +#pragma once +#include "AbstractRoguelikeTaskPlugin.h" +#include "Common/AsstTypes.h" + +namespace asst +{ + class RoguelikeCollapsalParadigmTaskPlugin : public AbstractRoguelikeTaskPlugin + { + public: + using AbstractRoguelikeTaskPlugin::AbstractRoguelikeTaskPlugin; + virtual ~RoguelikeCollapsalParadigmTaskPlugin() override = default; + + public: + virtual bool verify(AsstMsg msg, const json::value& details) const override; + + protected: + virtual bool _run() override; + + private: + const Rect m_roi = { 655, 20, 10, 10 }; // 屏幕上方居中区域,点击以检查坍缩状态 + const Point m_swipe_begin = {640, 300}; // 滑动起点 + const Point m_swipe_end = {640, 0}; // 滑动终点 + + mutable bool m_check_banner = false; + mutable bool m_check_panel = false; + mutable bool m_need_check_panel = false; + mutable bool m_verification_check = false; + mutable std::string m_level; + + const std::unordered_set m_banner_triggers_start = { + "NeedCheckCollapsalParadigmBanner", + "Sami@Roguelike@MissionCompletedFlag" + // "Sami@Roguelike@DropsFlag" + }; + + const std::unordered_set m_banner_triggers_completed = { + "Sami@Roguelike@GetDrop1", + "Sami@Roguelike@GetDrop2", + "Sami@Roguelike@GetDrop3", + "Sami@Roguelike@GetDrop4", + "Sami@Roguelike@GetDropSelectReward", + "Sami@Roguelike@GetDropSelectReward2", + // "Sami@Roguelike@ClickToDrops", + "Sami@Roguelike@TraderRandomShoppingConfirm" + }; + + const std::unordered_set m_panel_triggers = { + // 作战 + "Sami@Roguelike@StageCombatDps", + "Sami@Roguelike@StageCombatDpsAI6", + "Sami@Roguelike@StageVerticalCombatDps", + "Sami@Roguelike@StageVerticalCombatDpsAI6", + // 紧急作战 + "Sami@Roguelike@StageEmergencyDps", + "Sami@Roguelike@StageEmergencyDpsAI6", + "Sami@Roguelike@StageVerticalEmergencyDps", + "Sami@Roguelike@StageVerticalEmergencyDpsAI6", + // 险路恶敌 + "Sami@Roguelike@StageDreadfulFoe", + "Sami@Roguelike@StageDreadfulFoe-5", + // 不期而遇 + "Sami@Roguelike@StageEncounter", + "Sami@Roguelike@StageEncounterAI6", + "Sami@Roguelike@StageVerticalEncounter", + "Sami@Roguelike@StageVerticalEncounterAI6", + // 安全的角落 + "Sami@Roguelike@StageSafeHouse", + "Sami@Roguelike@StageSafeHouseAI6", + "Sami@Roguelike@StageVerticalSafeHouse", + "Sami@Roguelike@StageVerticalSafeHouseAI6", + // 兴致盎然 + "Sami@Roguelike@StageGambling", + "Sami@Roguelike@StageGamblingAI6", + "Sami@Roguelike@StageVerticalGambling", + "Sami@Roguelike@StageVerticalGamblingAI6", + // 命运所指 + "Sami@Roguelike@StageProphecy", + "Sami@Roguelike@StageProphecyAI6", + "Sami@Roguelike@StageVerticalProphecy", + "Sami@Roguelike@StageVerticalProphecyAI6", + // 得偿所愿 + "Sami@Roguelike@StageBoons", + "Sami@Roguelike@StageBoonsAI6", + "Sami@Roguelike@StageVerticalBoons", + "Sami@Roguelike@StageVerticalBoonsAI6", + // 诡意行商 + "Sami@Roguelike@StageTrader", + "Sami@Roguelike@StageTraderAI6", + "Sami@Roguelike@StageVerticalTrader", + "Sami@Roguelike@StageVerticalTraderAI6", + // 失与得 + "Sami@Roguelike@StageWindAndRain", + "Sami@Roguelike@StageWindAndRainAI6", + "Sami@Roguelike@StageVerticalWindAndRain", + "Sami@Roguelike@StageVerticalWindAndRainAI6", + // 先行一步 + "Sami@Roguelike@StageEmergencyTransportation", + "Sami@Roguelike@StageEmergencyTransportationAI6", + "Sami@Roguelike@StageVerticalEmergencyTransportation", + "Sami@Roguelike@StageVerticalEmergencyTransportationAI6", + // 树篱之途 + "Sami@Roguelike@StageBoskyPassage", + "Sami@Roguelike@StageBoskyPassageAI6", + "Sami@Roguelike@StageVerticalBoskyPassage", + "Sami@Roguelike@StageVerticalBoskyPassageAI6", + // 模糊的预感 + "Sami@Roguelike@StageMysteriousPresage", + "Sami@Roguelike@StageFerociousPresage" + }; + + bool new_level() const; + + bool check_collapsal_paradigm_banner(); + bool check_collapsal_paradigm_panel(); + + void toggle_collapsal_status_panel(); + void exit_then_restart(); + void exit_then_stop(); + void wait_for_loading(unsigned int millisecond = 0); + void wait_for_stage(unsigned int millisecond = 0); + void clp_pd_callback(std::string cur, int deepen_or_weaken = 0, std::string prev = ""); + }; +} diff --git a/src/MaaCore/Task/Roguelike/RoguelikeConfig.cpp b/src/MaaCore/Task/Roguelike/RoguelikeConfig.cpp index d7ecc4b662..944c33a073 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeConfig.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeConfig.cpp @@ -13,4 +13,6 @@ void asst::RoguelikeConfig::clear() m_foldartal_floor.reset(); m_foldartal = std::vector(); + + m_clp_pds = std::vector(); } diff --git a/src/MaaCore/Task/Roguelike/RoguelikeConfig.h b/src/MaaCore/Task/Roguelike/RoguelikeConfig.h index 93f8d34969..2279254ace 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeConfig.h +++ b/src/MaaCore/Task/Roguelike/RoguelikeConfig.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace asst { @@ -13,6 +14,7 @@ namespace asst // 2 - 【已移除】两者兼顾,投资过后再退出,没有投资就继续往后打 Ending = 3, // 3 - 尝试通关,激进策略(TODO) Collectible = 4, // 4 - 刷开局,以获得热水壶或者演讲稿开局或只凹直升,不期而遇采用保守策略 + CLP_PDS = 5 // 5 - 刷隐藏坍缩范式,以增加坍缩值为最优先目标 }; class RoguelikeTheme @@ -38,10 +40,11 @@ namespace asst { return theme == RoguelikeTheme::Phantom || theme == RoguelikeTheme::Mizuki || theme == RoguelikeTheme::Sami; } - static constexpr bool is_valid_mode(RoguelikeMode mode) + static constexpr bool is_valid_mode(RoguelikeMode mode, std::string_view theme = RoguelikeTheme::Sami) { return mode == RoguelikeMode::Exp || mode == RoguelikeMode::Investment || - mode == RoguelikeMode::Collectible; + mode == RoguelikeMode::Collectible || + (mode == RoguelikeMode::CLP_PDS && theme == RoguelikeTheme::Sami); } public: @@ -71,6 +74,12 @@ namespace asst bool get_invest_with_more_score() const { return m_invest_with_more_score; } void set_use_foldartal(bool use_foldrtal) { m_use_foldartal = use_foldrtal; } bool get_use_foldartal() const {return m_use_foldartal; } + void set_check_clp_pds(bool check_clp_pds) { m_check_clp_pds = check_clp_pds; } + bool get_check_clp_pds() const {return m_check_clp_pds; } + void set_double_check_clp_pds(bool double_check_clp_pds) { m_double_check_clp_pds = double_check_clp_pds; } + bool get_double_check_clp_pds() const {return m_double_check_clp_pds; } + void set_expected_clp_pds(std::unordered_set expected_clp_pds) { m_expected_clp_pds = expected_clp_pds; } + std::unordered_set get_expected_clp_pds() const { return m_expected_clp_pds; } private: std::string m_theme; // 主题 @@ -86,6 +95,9 @@ namespace asst bool m_invest_stop_when_full = false; // 存款满了就停止 bool m_invest_with_more_score = false; // 投资时招募、购物刷分 bool m_use_foldartal = true; // 是否使用密文板 + bool m_check_clp_pds = false; // 是否检查坍缩范式 + bool m_double_check_clp_pds = false; // 是否反复检查坍缩范式 + std::unordered_set m_expected_clp_pds; // 期望获得坍缩范式 /* 以下为每次重置 */ public: @@ -111,6 +123,8 @@ namespace asst const std::optional& get_foldartal_floor() const { return m_foldartal_floor; } void set_foldartal(std::vector foldartal) { m_foldartal = std::move(foldartal); } const std::vector& get_foldartal() const { return m_foldartal; } + void set_clp_pds(std::vector clp_pds) { m_clp_pds = std::move(clp_pds); } + const std::vector& get_clp_pds() const { return m_clp_pds; } private: int m_recruitment_count = 0; // 招募次数 @@ -124,5 +138,6 @@ namespace asst std::unordered_map m_oper; // 干员精英&等级 std::optional m_foldartal_floor; // 当前层的预见密文板,在下一层获得 std::vector m_foldartal; // 所有已获得密文板 + std::vector m_clp_pds; // 已受到的坍缩范式 }; } // namespace asst diff --git a/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.cpp index fd5ba3bfe0..4b285dd7d2 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.cpp @@ -164,6 +164,10 @@ void asst::RoguelikeFoldartalUseTaskPlugin::use_enable_pair( list.erase(ranges::find(list, up_board)); list.erase(ranges::find(list, down_board)); Log.trace("Board pair used, up:", up_board, ", down:", down_board); + callback(AsstMsg::SubTaskStart, json::object { + { "subtask", "ProcessTask" }, + { "details", json::object { { "task", "NeedCheckCollapsalParadigmBanner" }, { "pre_task", "RoguelikeFoldartalUseTask"} } } + }); break; } } diff --git a/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.h index 4c5902a9ac..60354d38fb 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.h +++ b/src/MaaCore/Task/Roguelike/RoguelikeFoldartalUseTaskPlugin.h @@ -1,13 +1,22 @@ #pragma once #include "AbstractRoguelikeTaskPlugin.h" #include "Config/Roguelike/RoguelikeFoldartalConfig.h" +#include "RoguelikeCollapsalParadigmTaskPlugin.h" namespace asst { class RoguelikeFoldartalUseTaskPlugin : public AbstractRoguelikeTaskPlugin { public: - using AbstractRoguelikeTaskPlugin::AbstractRoguelikeTaskPlugin; + // using AbstractRoguelikeTaskPlugin::AbstractRoguelikeTaskPlugin; + RoguelikeFoldartalUseTaskPlugin(const AsstCallback& callback, + Assistant* inst, + std::string_view task_chain, + std::shared_ptr config) + : AbstractRoguelikeTaskPlugin(callback, inst, task_chain, config) + { + register_plugin(config); + } virtual ~RoguelikeFoldartalUseTaskPlugin() override = default; public: diff --git a/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp index 559c2ecf20..39ef56800b 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeShoppingTaskPlugin.cpp @@ -117,6 +117,7 @@ bool asst::RoguelikeShoppingTaskPlugin::buy_once() m_config->get_theme() == RoguelikeTheme::Sami ? Task.get("Sami@Roguelike@FoldartalGainOcr")->text : std::vector(); + const RoguelikeMode& mode = m_config->get_mode(); for (const auto& goods : all_goods) { if (need_exit()) { return false; @@ -124,6 +125,9 @@ bool asst::RoguelikeShoppingTaskPlugin::buy_once() if (no_longer_buy && !goods.ignore_no_longer_buy) { continue; } + if (mode == RoguelikeMode::CLP_PDS && goods.decrease_collapse) { + continue; + } auto find_it = ranges::find_if(result, [&](const TextRect& tr) -> bool { return tr.text.find(goods.name) != std::string::npos diff --git a/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.cpp index 033c56631f..3106510e99 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.cpp @@ -36,11 +36,15 @@ bool asst::RoguelikeStageEncounterTaskPlugin::_run() { LogTraceFunction; - auto mode = m_config->get_mode(); - std::vector events = RoguelikeStageEncounter.get_events(m_config->get_theme()); + const std::string& theme = m_config->get_theme(); + const RoguelikeMode& mode = m_config->get_mode(); + std::vector events = RoguelikeStageEncounter.get_events(theme); // 刷源石锭模式和烧水模式 if (mode == RoguelikeMode::Investment || mode == RoguelikeMode::Collectible) { - events = RoguelikeStageEncounter.get_events(m_config->get_theme() + "_deposit"); + events = RoguelikeStageEncounter.get_events(theme + "_deposit"); + } + if (mode == RoguelikeMode::CLP_PDS) { + events = RoguelikeStageEncounter.get_events(theme + "_collapse"); } std::vector event_names; std::unordered_map event_map; @@ -104,6 +108,10 @@ bool asst::RoguelikeStageEncounterTaskPlugin::_run() ProcessTask(*this, { click_option_task_name(choose_option, event.option_num) }).run(); sleep(300); } + callback(AsstMsg::SubTaskStart, json::object { + { "subtask", "ProcessTask" }, + { "details", json::object { { "task", "NeedCheckCollapsalParadigmBanner" }, { "pre_task", "RoguelikeStageEncounterTask"} } } + }); // 判断是否点击成功,成功进入对话后左上角的生命值会消失 sleep(500); @@ -120,6 +128,10 @@ bool asst::RoguelikeStageEncounterTaskPlugin::_run() ProcessTask(*this, { click_option_task_name(i, max_time) }).run(); sleep(300); } + callback(AsstMsg::SubTaskStart, json::object { + { "subtask", "ProcessTask" }, + { "details", json::object { { "task", "NeedCheckCollapsalParadigmBanner" }, { "pre_task", "RoguelikeStageEncounterTask"} } } + }); if (need_exit()) { return false; diff --git a/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h index 89f9bbb982..d018c16d07 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h +++ b/src/MaaCore/Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h @@ -3,13 +3,22 @@ #include "Config/Roguelike/RoguelikeStageEncounterConfig.h" #include "Config/TaskData.h" #include "Vision/OCRer.h" +#include "RoguelikeCollapsalParadigmTaskPlugin.h" namespace asst { class RoguelikeStageEncounterTaskPlugin : public AbstractRoguelikeTaskPlugin { public: - using AbstractRoguelikeTaskPlugin::AbstractRoguelikeTaskPlugin; + // using AbstractRoguelikeTaskPlugin::AbstractRoguelikeTaskPlugin; + RoguelikeStageEncounterTaskPlugin(const AsstCallback& callback, + Assistant* inst, + std::string_view task_chain, + std::shared_ptr config) + : AbstractRoguelikeTaskPlugin(callback, inst, task_chain, config) + { + register_plugin(config); + } using Config = RoguelikeStageEncounterConfig; virtual ~RoguelikeStageEncounterTaskPlugin() override = default;