diff --git a/docs/3.7-保全派驻协议.md b/docs/3.7-保全派驻协议.md index 3a68c26618..e772afd08d 100644 --- a/docs/3.7-保全派驻协议.md +++ b/docs/3.7-保全派驻协议.md @@ -28,18 +28,19 @@ ], "tool_men": { // 剩余所需各职业人数,按费用排序随便拿,可选 "Pioneer": 13, - "Warrior": 2, // 中英文均可 + "近卫": 2, // 中英文均可 "Medic": 2 }, - "drop_buffs": [ // 战斗后拿buff的优先级。好像只有第四层有?可选 - "定向部署支援系统" - ], - "drop_tool_men": [ // 战斗结束后招募干员职业的优先级,可选 + "drops": [ // 战斗开始时和战斗中途,招募干员、获取装备优先级 "空弦", - "能天使", - "先锋", // 中英文均可 + "能天使", // 支持干员名、职业名 + "先锋", // 职业名中英文均可 "Support", - "无需增调干员" // 不招人 + "无需增调干员", // 不招人 + "重整导能组件", // 支持装备名,全写一起.jpg + "反制导能组件", + "战备激活阀", // 关卡中途的可选装备,也也放这里。需要配合 actions 中 type: GetDrops 使用 + "改派发讯器", ], "stages": [ { @@ -88,7 +89,6 @@ } ], "draw_as_possible": true, // “调配干员”按钮,是否好了就用,可选,默认 true - "actions": [ // 可选 // 基本复用抄作业的逻辑,可参考 3.3-战斗流程协议.md // 符合 action 的条件就执行 action,否则执行上面的 strategies 的逻辑 @@ -100,10 +100,16 @@ "name": "棘刺" }, { - "type": "CheckIfStartOver", // 检查干员在不在,不在就退出重开 - "tool_men": { - "Pioneer": 2 - } + "type": "CheckIfStartOver", // 新 type,检查战利品并获取 + "name": "棘刺" + }, + { + "type": "GetDrops", // 检查获取战斗中途的战利品,将按照 drops 字段的排序进行拿去 + // 若 drops 字段为空,或 drops 中的物品一个都没识别到,将会选择放弃战利品 + // 若执行动作时未识别到战利品获取,将会直接跳过该 action + "kills": 20, + "pre_delay": 3000 // 小技巧:一般来说都是打死了某个怪才会出,所以可以基于击杀数来触发 + // 但是从击杀数达到到选择界面跳出来可能有个延迟,所以建议价格 pre_delay }, { "name": "桃金娘", diff --git a/resource/copilot/SSS_Test.json b/resource/copilot/SSS_Test.json index 61b0ff0806..ad5ae3d173 100644 --- a/resource/copilot/SSS_Test.json +++ b/resource/copilot/SSS_Test.json @@ -33,15 +33,16 @@ "近卫": 6, "医疗": 2 }, - "drop_buffs": [ - "定向部署支援系统" - ], - "drop_tool_men": [ + "drops": [ "空弦", "能天使", "先锋", - "辅助", - "无需增调干员" + "Support", + "无需增调干员", + "重整导能组件", + "反制导能组件", + "战备激活阀", + "改派发讯器" ], "stages": [ { diff --git a/resource/tasks.json b/resource/tasks.json index 8e88ed72e3..f94ae8cc59 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -9439,14 +9439,19 @@ ] }, "SSSDropRecruitmentFlag": { + "algorithm": "OcrDetect", "action": "DoNothing", - "roi": [ - 0, - 39, - 250, - 203 + "text": [ + "请选择", + "请进行" ], - "postDelay": 2000, + "roi": [ + 163, + 78, + 900, + 112 + ], + "postDelay": 5000, "next": [ "SSSStartFighting2", "SSSDropRecruitmentFlag" @@ -9472,9 +9477,9 @@ "cache": false, "roi": [ 0, - 434, + 352, 1280, - 169 + 263 ] }, "SSSDropRecruitmentConfrim": { @@ -9482,13 +9487,64 @@ "action": "ClickSelf", "text": [ "确认调用", - "放弃调用" + "放弃调用", + "确认选择" ], "roi": [ 1105, 525, 175, 132 + ], + "preDelay": 1000, + "postDelay": 1000 + }, + "SSSHalfTimeDropsBegin": { + "algorithm": "JustReturn", + "action": "DoNothing", + "next": [ + "SSSHalfTimeDrops", + "SSSHalfTimeDropsCancel" + ] + }, + "SSSHalfTimeDrops": { + "algorithm": "OcrDetect", + "action": "ClickSelf", + "text": [], + "roi": [ + 206, + 452, + 897, + 88 + ], + "next": [ + "SSSHalfTimeDropsConfirm" + ] + }, + "SSSHalfTimeDropsConfirm": { + "algorithm": "OcrDetect", + "action": "ClickSelf", + "text": [ + "确认" + ], + "roi": [ + 1073, + 281, + 155, + 151 + ] + }, + "SSSHalfTimeDropsCancel": { + "algorithm": "OcrDetect", + "action": "ClickSelf", + "text": [ + "放弃" + ], + "roi": [ + 51, + 251, + 146, + 199 ] }, "ClickCornerUntilStartButton": { diff --git a/resource/template/SSSDropRecruitmentFlag.png b/resource/template/SSSDropRecruitmentFlag.png deleted file mode 100644 index 300c7920f5..0000000000 Binary files a/resource/template/SSSDropRecruitmentFlag.png and /dev/null differ diff --git a/src/MaaCore/Common/AsstBattleDef.h b/src/MaaCore/Common/AsstBattleDef.h index 665eb8e3f2..5acb70c69e 100644 --- a/src/MaaCore/Common/AsstBattleDef.h +++ b/src/MaaCore/Common/AsstBattleDef.h @@ -157,6 +157,7 @@ namespace asst::battle /* for SSS */ DrawCard, // “调配干员” CheckIfStartOver, // 检查如果没有某干员则退出重开 + GetDrops, // 识别并获取战斗中途的掉落物 }; struct Action @@ -212,6 +213,7 @@ namespace asst::battle std::vector strategies; bool draw_as_possible = false; int retry_times = 0; + std::vector order_of_drops; }; enum class EquipmentType @@ -231,8 +233,7 @@ namespace asst::battle copilot::OperUsageGroups groups; RoleCounts tool_men; - std::vector drop_buffs; - std::vector drop_tool_men; + std::vector order_of_drops; std::unordered_map stages_data; }; diff --git a/src/MaaCore/Config/Miscellaneous/CopilotConfig.cpp b/src/MaaCore/Config/Miscellaneous/CopilotConfig.cpp index 382e0a7fa6..6063d6ecd3 100644 --- a/src/MaaCore/Config/Miscellaneous/CopilotConfig.cpp +++ b/src/MaaCore/Config/Miscellaneous/CopilotConfig.cpp @@ -155,6 +155,14 @@ std::vector asst::CopilotConfig::parse_actions(co { "CHECKIFSTARTOVER", ActionType::CheckIfStartOver }, { "checkifstartover", ActionType::CheckIfStartOver }, { "检查重开", ActionType::CheckIfStartOver }, + + { "GetDrops", ActionType::GetDrops }, + { "Getdrops", ActionType::GetDrops }, + { "GETDROPS", ActionType::GetDrops }, + { "getdrops", ActionType::GetDrops }, + { "获取战利品", ActionType::GetDrops }, + { "获取掉落", ActionType::GetDrops }, + { "获取装备", ActionType::GetDrops }, }; std::string type_str = action_info.get("type", "Deploy"); diff --git a/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp b/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp index 1043c6ac54..f9aba5ba66 100644 --- a/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp +++ b/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp @@ -42,29 +42,13 @@ bool asst::SSSCopilotConfig::parse(const json::value& json) } } - if (auto drop_buffs = json.find("drop_buffs")) { - for (const auto& drop_buff : drop_buffs.value()) { - m_data.drop_buffs.emplace_back(drop_buff.as_string()); + if (auto drops_opt = json.find("drops")) { + m_data.order_of_drops.reserve(drops_opt->size()); + for (const auto& drop : *drops_opt) { + m_data.order_of_drops.emplace_back(drop.as_string()); } } - if (auto drop_tool_men = json.find("drop_tool_men")) { - for (const auto& man : drop_tool_men.value()) { - std::string name = man.as_string(); - if (auto role = get_role_type(name); role != Role::Unknown) { - m_data.drop_tool_men.emplace_back(name); - } - else if (BattleData.get_rarity(name) != 0) { - m_data.drop_tool_men.emplace_back(name); - } - else if (name == "None") { - m_data.drop_tool_men.emplace_back(name); - } - else { - Log.warn("Unknown drop tool man", name); - } - } - } for (const auto& stage : json.at("stages").as_array()) { CombatData stage_data; stage_data.info = CopilotConfig::parse_basic_info(stage); @@ -72,6 +56,7 @@ bool asst::SSSCopilotConfig::parse(const json::value& json) stage_data.actions = CopilotConfig::parse_actions(stage); stage_data.groups = m_data.groups; + stage_data.order_of_drops = m_data.order_of_drops; for (const auto& strategy_info : stage.at("strategies").as_array()) { Strategy strategy; diff --git a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp index a676e2700f..cd077c93ae 100644 --- a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp +++ b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp @@ -262,6 +262,9 @@ bool asst::BattleProcessTask::wait_condition(const Action& action) break; } } + if (!check_in_battle(image)) { + return false; + } do_strategy_and_update_image(); } } @@ -273,6 +276,9 @@ bool asst::BattleProcessTask::wait_condition(const Action& action) if (m_kills >= action.kills) { break; } + if (!check_in_battle(image)) { + return false; + } do_strategy_and_update_image(); } } @@ -284,6 +290,9 @@ bool asst::BattleProcessTask::wait_condition(const Action& action) if (m_cost >= action.costs) { break; } + if (!check_in_battle(image)) { + return false; + } do_strategy_and_update_image(); } } @@ -298,6 +307,9 @@ bool asst::BattleProcessTask::wait_condition(const Action& action) if (cooling_count == action.cooling) { break; } + if (!check_in_battle(image)) { + return false; + } do_strategy_and_update_image(); } } @@ -312,6 +324,9 @@ bool asst::BattleProcessTask::wait_condition(const Action& action) iter != m_cur_deployment_opers.cend() && iter->second.available) { break; } + if (!check_in_battle(image)) { + return false; + } do_strategy_and_update_image(); } } diff --git a/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp b/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp index f14de4297f..384f645458 100644 --- a/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp +++ b/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp @@ -1,6 +1,7 @@ #include "SSSBattleProcessTask.h" #include "Config/Miscellaneous/SSSCopilotConfig.h" +#include "Config/TaskData.h" #include "Controller.h" #include "Task/ProcessTask.h" #include "Utils/Logger.hpp" @@ -47,6 +48,8 @@ bool asst::SSSBattleProcessTask::do_derived_action(size_t action_index) return draw_card(); case battle::copilot::ActionType::CheckIfStartOver: return check_if_start_over(action); + case battle::copilot::ActionType::GetDrops: + return get_drops(); default: Log.error("unknown action type", static_cast(action.type)); return false; @@ -161,9 +164,27 @@ bool asst::SSSBattleProcessTask::check_if_start_over(const battle::copilot::Acti bool asst::SSSBattleProcessTask::draw_card(bool with_retry) { + LogTraceFunction; + ProcessTask task(*this, { "SSSDrawCard" }); if (!with_retry) { task.set_retry_times(0); } return task.run(); } + +bool asst::SSSBattleProcessTask::get_drops() +{ + LogTraceFunction; + + const auto& drops = m_sss_combat_data.order_of_drops; + + // 不一定就有掉落界面,有可能宝箱怪压根没被打掉。所以不重试 + if (drops.empty()) { + return ProcessTask(*this, { inst_string() + "@SSSHalfTimeDropsCancel" }).set_retry_times(0).run(); + } + else { + Task.get(inst_string() + "@SSSHalfTimeDrops")->text = { drops }; + return ProcessTask(*this, { inst_string() + "@SSSHalfTimeDropsBegin" }).set_retry_times(0).run(); + } +} diff --git a/src/MaaCore/Task/SSS/SSSBattleProcessTask.h b/src/MaaCore/Task/SSS/SSSBattleProcessTask.h index dc031ebede..0df5ff24e0 100644 --- a/src/MaaCore/Task/SSS/SSSBattleProcessTask.h +++ b/src/MaaCore/Task/SSS/SSSBattleProcessTask.h @@ -21,6 +21,7 @@ namespace asst bool check_if_start_over(const battle::copilot::Action& action); bool draw_card(bool with_retry = true); + bool get_drops(); battle::sss::CombatData m_sss_combat_data; std::unordered_set m_all_cores; diff --git a/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp b/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp index 7846cbb54f..f28644c1de 100644 --- a/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp +++ b/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp @@ -44,7 +44,7 @@ bool asst::SSSDropRewardsTaskPlugin::_run() .ocr_res = result, .role = role == Role::Unknown ? std::nullopt : std::optional(role) }); } - for (const std::string& name : SSSCopilot.get_data().drop_tool_men) { + for (const std::string& name : SSSCopilot.get_data().order_of_drops) { auto role = get_role_type(name); bool is_role = role != Role::Unknown; auto iter = ranges::find_if(opers, [&](const DropRecruitment& props) {