MAA 明日方舟助手 SSS 保全派驻协议详解:从 JSON 字段到战斗主循环的源码解析
【免费下载链接】MaaAssistantArknights《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients.项目地址: https://gitcode.com/GitHub_Trending/ma/MaaAssistantArknights
本文以 保全派驻协议文档 为主体,完整讲解 MaaAssistantArknights(MAA)中type: "SSS"保全派驻协议的全部字段含义、单关策略strategies的判定规则与actions用法,并结合 SSSCopilotConfig.cpp、SSSBattleProcessTask.cpp 等源码,还原协议从加载、开局换人、战斗主循环到阶段管理的完整执行链路,帮助你从零写出可用的保全派驻作业 JSON。
一、协议定位:SSS 与 copilot 协议的关系
保全派驻(游戏内 LT/SS 玩法,协议中以SSS指代)是 roguelike 式多关卡战斗:开局选干员与导能元件,中途可增调干员与装备,战斗失败可重开整局。为此 MAA 在通用战斗流程协议(copilot 协议)之外定义了 SS 协议,核心差异在于:
- 单份 JSON 描述多个关卡(
stages数组),程序按屏幕识别到的关卡名逐关执行; - 每关支持
strategies(按格子声明“核心干员 + 工具人”的自适应部署计划)与drops(中途增调优先级),而不是一条固定时间轴; - 提供了 SSS 专属 action 类型,如
调配干员、CheckIfStartOver。
从源码结构看,SS 作业数据继承自 copilot 的数据结构:AsstBattleDef.h 中namespace sss定义了Strategy(含可选core、tool_men、location、direction与完成标记all_deployed)、CombatData(继承copilot::CombatData,新增strategies、draw_as_possible、retry_times、order_of_drops)与CompleteData(整份协议,含buff、equipment、strategy、groups、tool_men、order_of_drops、blacklist与按关名索引的stages_data)。
协议文件通过SSSTask的set_params以filename参数加载(通常放在resource/copilot/目录下,与 copilot 作业同目录,可参考 协议文档中的示例文件说明)。SSSCopilotTask.cpp 中可见:set_params校验filename后调用SSSCopilot.load()解析,解析失败即报错退出;若buff非空,则将其写入 OCR 任务@SSSBuffChoose的候选文本,用于开局选择导能元件。
二、协议 JSON 完整字段一览
注意:JSON 文件本身不支持注释,以下注释仅用于说明,请勿直接复制使用(原文档同样有此提示)。
{ "type": "SSS", // 协议类型,SSS 表示保全派驻,必选,不可修改 "stage_name": "多索雷斯在建地块", // 保全派驻地图名,必选 "minimum_required": "v4.9.0", // 最低要求 maa 版本号,必选 "doc": { // 描述,可选 "title": "低练度高成功率作业", "title_color": "dark", "details": "对练度要求很低balabala……", // 建议在这里写上你的名字!(作者名)、参考的视频攻略链接等 "details_color": "dark" }, "buff": "自适应补给元件", // 开局导能元件选择,可选 "equipment": [ // 开局装备选择,横着数,可选 // 当前版本暂未实现,只会在界面上显示一下 "A", "A", "A", "A", "B", "B", "B", "B" ], "strategy": "优选策略", // 或者 自由策略,可选 // 当前版本暂未实现,只会在界面上显示一下 "opers": [ // 指定干员,可选 { "name": "棘刺", "skill": 3, "skill_usage": 1 } ], "groups": [ // 干员编组,可选,用法同 copilot 协议中的 groups,actions 中的 name 可以填编组名 { "name": "地面阻挡", "opers": [ { "name": "棘刺", "skill": 3 }, { "name": "泥岩", "skill": 2 } ] } ], "tool_men": { // 剩余所需各职业人数,按费用排序随便拿,必选 // 当前版本暂未实现,只会在界面上显示一下 "Pioneer": 13, "近卫": 2, // 中英文均可 "Medic": 2 }, "drops": [ // 战斗开始时和战斗中途,招募干员、获取装备优先级 "空弦", "能天使", // 支持干员名、职业名 "先锋", // 职业名中英文均可 "Support", "无需增调干员", // 不招人 "重整导能组件", // 支持装备名,全写一起.jpg "反制导能组件", "战备激活阀", // 关卡中途的可选装备,也放这里 "改派发讯器" ], "blacklist": [ // 黑名单,可选。在 drops 里不会选这些人。 // 后续版本支持编队后,编队工具人也不会选这些人 "夜半", "梅尔" ], "stages": [ { "stage_name": "蜂拥而上", // 单层关卡名,必选 // 支持 name, stageId, levelId,推荐 stageId 或 levelId // 请勿使用 code(例如 LT-1),因为会和其他保全关卡冲突 "strategies": [ // 必选 // 每次检查都会从头自上而下依次进行,并跳过执行完毕的策略 // 若当前策略的工具人已经部署完毕 // 若没有 core,则认为此策略执行完毕 // 若有 core 且可以部署,则部署 core 并认为策略执行完毕 // 若有 core 正在转费用,则等待并跳过后续策略 // 若当前策略的工具人还未部署完毕 // 若部署区没有所需工具人,则检查下一条策略 // 若部署区存在所需工具人 // 若没有能立即部署的,则等待 // 若存在能立即部署的,则优先部署费用少的 // 对于同一格的策略, // 若没有 core,则允许在待部署区没有所需工具人时(不论费用是否转好),允许继续检查同一格后续策略 // 若有 core,则没有执行完毕时忽略同一格后续策略 // 同一格可以写多个干员 core,非最靠后的干员 core 在其策略执行完毕后等效过牌(不计入工具人) { "core": "棘刺", "tool_men": { "Pioneer": 1, // 中英文均可 "Warrior": 1, "Medic": 1 }, "location": [ 10, 1 ], "direction": "Left" }, { "core": "泥岩", "tool_men": { "Pioneer": 1, "Warrior": 1, "Medic": 1 }, "location": [ 2, 8 ], "direction": "Left" }, { // 不填写 core,可以用于部署辅助过牌的之类的 "tool_men": { "Support": 100 }, "location": [ 2, 8 ], "direction": "Left" } ], "draw_as_possible": true, // “调配干员”按钮,是否好了就用,必选 "actions": [ // 可选 // 基本复用抄作业的逻辑,可参考 protocol/copilot-schema.md // 符合 action 的条件就执行 action,否则执行上面的 strategies 的逻辑 { "type": "调配干员" // 新 type,“调配干员” 按钮,点一下,在 "draw_as_possible" 为 true 时无效 }, { "type": "CheckIfStartOver", // 新 type,检查干员在不在,不在就退出重开 "name": "棘刺" }, { "name": "桃金娘", "location": [ 4, 5 ], "direction": "左" }, { "kills": 10, "type": "撤退", "name": "桃金娘" } ], "retry_times": 3 // 战斗失败重试次数,可选,默认为 0,超过了直接放弃整局 }, { "stage_name": "见者有份" // ... } // 写几关打几关,比如只写到了 4,则打完 4 自动重开 ] }三、顶层字段逐项说明(含源码佐证)
3.1 基本信息与版本约束
type、stage_name、minimum_required、doc均由 copilot 的基础信息解析逻辑统一处理:SSSCopilotConfig.cpp 中parse()先调用CopilotConfig::parse_basic_info(json)解析出BasicInfo(对应 AsstBattleDef.h 中的stage_name、minimum_required、title、title_color、details、details_color),随后解析groups。doc中的title/details用于界面展示,适合署名与贴攻略链接。
3.2 buff / equipment / strategy / opers:开局选项
buff:解析后若非空,会写入@SSSBuffChooseOCR 任务作为开局元件选择候选(见 SSSCopilotTask.cpp),是实际生效的字段;equipment:解析时只接受A/B(大小写均可),且长度不为 8 会输出equipment size is not 8警告(SSSCopilotConfig.cpp);如文档所述,当前版本暂未实现开局装备的实际选择,仅解析保存;strategy(优选/自由策略)与顶层opers:同样解析或仅用于展示,当前版本未参与实际决策。
3.3 groups:编组语法复用 copilot
groups由CopilotConfig::parse_groups解析(SSSCopilotConfig.cpp),并在每关解析时下发给该关的CombatData(stage_data.groups = m_data.groups,SSSCopilotConfig.cpp),因此strategies/actions里的name均可填编组名,用法与 copilot 协议 完全一致:编组内干员任选其一,优先选练度高的。
3.4 tool_men:整局职业配额
顶层tool_men通过parse_role_counts解析为职业人数表(中英文职业名均可)。按文档说明,当前版本它只在界面展示;从源码看,配套的自动编队任务BattleFormationTask虽然被挂入了任务链,但 SSSCopilotTask.cpp 中AdditionalFormation相关代码被注释并显式set_enable(false)(“暂时不支持自动编队”),与文档描述互相印证。
3.5 drops / blacklist:中途增调优先级
drops被原样存入order_of_drops(SSSCopilotConfig.cpp),战斗开始与半程补给时按此优先级招募干员、获取装备。战斗中的具体执行在 SSSBattleProcessTask.cpp 的check_and_get_drops():
- 先识别半程补给界面(
SSSHalfTimeDropsBegin); - 若
drops为空数组,执行@SSSHalfTimeDropsCancel(直接取消增调); - 否则把
drops全列表写入 OCR 任务@SSSHalfTimeDrops的候选文本,按列表顺序 OCR 匹配并点击——这也解释了为什么列表里可以混写干员名、职业名、装备名(如Support、反制导能组件),匹配到哪个选哪个;无需增调干员则对应界面上的不招募按钮。
blacklist存入CompleteData::blacklist(std::unordered_set<std::string>,AsstBattleDef.h)。按文档说明,其作用是让drops选择不命中这些干员,后续支持自动编队后同样会排除这些“工具人”。
四、单关字段:stages 与 strategies 判定规则
4.1 stage_name 的解析与匹配
每关的stage_name支持 name、stageId、levelId(推荐 stageId/levelId),文档特别强调不要使用 LT-1 这类 code,因为会与其他保全关卡冲突。源码中对应机制是:解析时通过Tile.find(stage_name)查询该关对应的屏幕显示名(ocr_code),并以显示名为 key 存入stages_data(SSSCopilotConfig.cpp)。运行时 SSSStageManagerTask.cpp 的analyze_stage()用 OCR 任务SSSStageNameOCR读取屏幕关卡名,再与stages_data的 key 做精确匹配——匹配不到时,程序会判定为通关界面(报SSSGamePass)或走结算退出。这就是“写几关打几关”的实现:写到第 4 关为止,第 5 关的名字不在 JSON 中,本局即自动结算放弃。
4.2 strategies 的判定语义
strategies是 SS 协议的核心:按数组顺序自上而下逐条检查,跳过已完成的策略,规则与文档注释一致。SSSBattleProcessTask.cpp 的check_and_do_strategy()实现了完整决策,可逐条印证文档中的规则:
- 跳过已完成策略:
strategy.all_deployed为真直接跳过(对应“跳过执行完毕的策略”); - 同格互斥:用
loc_with_strategy记录已有未完结策略的格子,后续同格策略被跳过;但只有带 core 的策略在等待时才会占用该格(if (strategy.core.has_value()) loc_with_strategy.emplace(...)),不带 core 的策略在待部署区没有所需工具人时会继续检查同格后续策略——与文档“若没有 core,则允许继续检查同一格后续策略”逐字对应; - core 优先部署:当 core 在待部署区、且该策略的
tool_men全部部署完时(use_the_core),若 core 费用已转好则立即部署并标记all_deployed;若 core 还在转费用则return false原地等待,并阻塞后续策略(对应“若有 core 正在转费用,则等待并跳过后续策略”); - 工具人部署:若
tool_men未满,则从待部署区找一个职业匹配且费用已转好的干员部署,同时确保不会把其他策略的 core 当工具人点掉(!m_all_cores.contains(oper.name));部署的工具人技能会被统一设为“好了就用”(SkillUsage::Possibly,SSSBattleProcessTask.cpp); - 等待语义:待部署区存在所需职业但都在转费用时返回 false 等待;都不存在时检查下一条策略。
另外文档中“同一格可写多个干员 core,非最靠后的干员 core 执行完毕后等效过牌”的设计,与源码中部署 core 后将其从m_all_cores移除(SSSBattleProcessTask.cpp)的行为一致:已部署的 core 不再受后续策略约束。
4.3 draw_as_possible
该字段必选,对应“调配干员”按钮。在战斗主循环 SSSBattleProcessTask.cpp 的do_strategic_action()中,每轮检查完 drops、strategies 与“好了就用”技能后,若draw_as_possible为 true 就尝试点一次SSSDrawCard(无重试、零延迟的轻量检查)。开启后,动作列表中显式的{"type": "调配干员"}就不再需要——文档亦注明其“在 draw_as_possible 为 true 时无效”。
4.4 actions:复用 copilot + 两个 SSS 专属 type
单关actions基本复用 copilot 协议 的操作逻辑(部署/技能/撤退/二倍速/条件kills/costs/cost_changes/elapsed_time等均同前)。执行顺序是:符合 action 条件就执行 action,否则执行 strategies 逻辑。SS 协议新增了两个 type,在 SSSBattleProcessTask.cpp 的do_derived_action()中分发:
调配干员(DrawCard):点击“调配干员”按钮并刷新待部署区识别;CheckIfStartOver:检查干员是否还在场上或待部署区,不在则放弃本局重开。SSSBattleProcessTask.cpp 中check_if_start_over()的实现是:name指定时,在待部署区与战场上都找不到该干员即调用abandon();也可用role_counts校验某职业人数不足。常用于开局几秒内确认关键干员(如指定 core)没有被随机换走。
4.5 retry_times:整局容错
retry_times可选,默认 0。SSSStageManagerTask.cpp 的preprocess_data()将其转换为每关的可用次数retry_times + 1(即含首战);主循环 SSSStageManagerTask.cpp 中,某关战斗结束后计数减一,次数耗尽则回调SSSSettlement(why: "Can't win, run!")并走结算流程放弃整局。
五、战斗执行链路:从 set_params 到逐关推进
5.1 任务链组装
SSSCopilotTask.cpp 的构造函数展示了完整子任务链:
@SSSBegin+SSSStartFighting:进入保全派驻并点击开战(含选地图、选元件@SSSBuffChoose等界面流程);BattleFormationTask(DataResource::SSSCopilot):自动编队占位,当前被禁用;@SSSTeamConfirm+SSSStartFighting:确认编队再次开战;SSSStageManagerTask:阶段管理主循环,注册了SSSDropRewardsTaskPlugin处理干员掉落奖励。
set_params还支持loop_times参数(默认 1):大于 1 时把上述子任务链整体复制多份顺序执行(SSSCopilotTask.cpp),即连打多局。
5.2 开局自动换人
进入战斗前的wait_until_start()(SSSBattleProcessTask.cpp)实现了一套开局预选替换逻辑,属于源码层面的实用细节:
- 默认最多替换 4 人,费用阈值 29(费用低于该值不替换);
- 若场上先锋少于 2 个,阈值降为 25,试图换出先锋保证费用运转;
- 待部署区若出现“超重绝缘水泥”这类 Drone 装置,直接丢弃(不计入替换数);
- 若作业中指定了“超重绝缘水泥”为 core,则只额外换 1 人,防止把它换掉。
5.3 战斗主循环的帧率与轮询节奏
do_strategic_action()每轮依次做四件事:check_and_get_drops(半程补给)→check_and_do_strategy(格子策略)→use_all_ready_skill(全场“好了就用”技能)→ 按draw_as_possible尝试调配干员(SSSBattleProcessTask.cpp)。两个值得注意的工程细节:
- 帧率限制:每轮截屏间隔受
Config.get_options().sss_fight_screencap_interval控制(毫秒级限帧,防止空转占满 CPU),可在 MAA 配置中调整; - 自适应轮询间隔:
update_deployment_with_skip()在连续 30 秒待部署区无变化时(通常进入挂机阶段),把识别间隔拉大到 1 秒,有变化则立即恢复 0 间隔(SSSBattleProcessTask.cpp)。
5.4 阶段管理:逐关识别与结算
SSSStageManagerTask.cpp 的_run()主循环是整局骨架:
等待战斗结束(SSSConfirmBattleComplete) → OCR 识别当前关卡名(SSSStageNameOCR) ├─ 识别失败:若处于开始界面 → 报 SSSTask SSSGamePass(通关) │ 否则 → 报 SSSTask SSSSettlement(识别错误或 JSON 不支持该关)并结算退出 └─ 命中 stages_data:扣减重试次数 → 点击开始(SSSStartFighting / SSSTask SSSTask SSSTask SSSTask SSSTask SSSTask) → 运行 SSSBattleProcessTask 打本关 → 回到循环顶部识别失败的回调文案Recognition error or JSON does not support this.也再次说明:JSON 里没写的关卡会被视为“不支持”,程序主动结算本局。
六、编写协议的建议清单
- 必选字段别漏:顶层
type、stage_name、minimum_required、tool_men;每关stage_name、strategies、draw_as_possible; - 关卡名用 stageId/levelId,避免 LT 系 code 冲突;
stages按实际出关顺序书写,写多少关就打算打多少关; - strategies 设计:关键位写
core+ 少量tool_men(按职业配额而非指定干员,容错性最好);纯工具位可不写 core;同格多 core 时把主力放最后; - drops 优先级:把最想要的人/职业/装备放最前,
无需增调干员放在不想招人的场景;不想见的干员进blacklist; - 稳定性兜底:给易翻车的关键关设置
retry_times;开局用CheckIfStartOver检查关键干员;actions里可用kills等条件插入撤退、加速等操作; - 命名与署名:
doc.details中写明作者与攻略出处,方便社区追溯。
参考文件
- 协议文档:docs/zh-cn/protocol/sss-schema.md、docs/zh-cn/protocol/copilot-schema.md
- 协议解析:src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp
- 任务入口与参数:src/MaaCore/Task/Interface/SSSCopilotTask.cpp
- 战斗执行:src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp、src/MaaCore/Task/SSS/SSSStageManagerTask.cpp
- 数据结构:src/MaaCore/Common/AsstBattleDef.h
【免费下载链接】MaaAssistantArknights《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients.项目地址: https://gitcode.com/GitHub_Trending/ma/MaaAssistantArknights
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考