diff --git a/resource/roguelike/copilot.json b/resource/roguelike/copilot.json index 8a90ca4c94..51e238663c 100644 --- a/resource/roguelike/copilot.json +++ b/resource/roguelike/copilot.json @@ -125,9 +125,9 @@ ], "deploy_plan": [ { - "groups": [ "百嘉", "基石", "地面C", "号角", "挡人先锋", "重装", "其他地面", "异德", "刺客" ], - "location": [ 6, 3 ], - "direction": "left" + "groups": [ "控制", "召唤", "高台C", "术师", "狙击", "辅助" ], + "location": [ 5, 1 ], + "direction": "down" }, { "groups": [ "控制", "召唤", "高台C", "术师", "狙击", "辅助" ], @@ -135,24 +135,29 @@ "direction": "left" }, { - "groups": [ "百嘉", "基石", "地面C", "玛恩纳", "号角", "地刺", "刺客", "重装", "挡人先锋" ], - "location": [ 7, 3 ], + "groups": [ "百嘉", "基石", "地面C", "号角", "挡人先锋", "重装", "其他地面", "异德", "刺客" ], + "location": [ 6, 3 ], "direction": "left" }, { - "groups": [ "单奶", "群奶" ], + "groups": [ "百嘉", "基石", "地面C", "玛恩纳", "号角", "地刺", "刺客", "重装", "挡人先锋" ], + "location": [ 4, 4 ], + "direction": "up" + }, + { + "groups": [ "单奶", "群奶", "召唤", "高台C", "控制", "术师", "狙击", "辅助", "其他高台" ], "location": [ 6, 1 ], "direction": "down" }, { - "groups": [ "召唤", "高台C", "控制", "术师", "狙击", "辅助", "其他高台" ], - "location": [ 5, 1 ], + "groups": [ "地面C", "异德", "地刺", "刺客", "挡人先锋", "其他地面" ], + "location": [ 5, 4 ], "direction": "down" }, { - "groups": [ "地面C", "异德", "地刺", "刺客", "挡人先锋", "其他地面" ], - "location": [ 4, 4 ], - "direction": "up" + "groups": [ "百嘉", "基石", "地面C", "玛恩纳", "号角", "地刺", "刺客", "重装", "挡人先锋" ], + "location": [ 7, 3 ], + "direction": "left" } ] }, @@ -192,12 +197,12 @@ "direction": "down" }, { - "groups": [ "召唤", "高台C", "控制", "术师", "狙击", "辅助" ], + "groups": [ "高台C", "召唤", "控制", "术师", "狙击", "辅助" ], "location": [ 2, 4 ], "direction": "down" }, { - "groups": [ "单奶", "群奶" ], + "groups": [ "单奶", "群奶", "高台C", "召唤", "控制", "术师", "狙击", "辅助" ], "location": [ 2, 3 ], "direction": "right" }, @@ -206,6 +211,11 @@ "location": [ 4, 3 ], "direction": "right" }, + { + "groups": [ "高台C", "召唤", "控制", "术师", "狙击", "辅助" ], + "location": [ 3, 6 ], + "direction": "left" + }, { "groups": [ "地面C", "玛恩纳", "号角", "异德", "地刺", "刺客", "挡人先锋", "其他地面" ], "location": [ 3, 2 ], @@ -270,6 +280,11 @@ } ], "deploy_plan": [ + { + "groups": [ "异德", "刺客" ], + "location": [ 6, 1 ], + "direction": "right" + }, { "groups": [ "挡人先锋", "投锋", "重装" ], "location": [ 6, 4 ], @@ -281,7 +296,7 @@ "direction": "left" }, { - "groups": [ "单奶", "群奶" ], + "groups": [ "单奶", "群奶", "高台C", "控制", "召唤", "术师", "狙击", "辅助" ], "location": [ 7, 5 ], "direction": "left" }, @@ -301,11 +316,10 @@ "direction": "down" }, { - "groups": [ "基石", "地面C", "刺客" ], + "groups": [ "基石", "地面C", "刺客", "其他地面" ], "location": [ 6, 6 ], "direction": "right" }, - { "groups": [ "召唤", "高台C", "控制", "术师", "狙击", "辅助", "其他高台" ], "location": [ 5, 6 ], @@ -434,28 +448,33 @@ }, { "groups": [ "玛恩纳" ], - "location": [ 7, 5 ], + "location": [ 7, 4 ], "direction": "left" }, { - "groups": [ "号角" ], - "location": [ 10, 4 ], + "groups": [ "号角", "百嘉", "基石", "地面C", "挡人先锋", "重装", "其他地面" ], + "location": [ 9, 4 ], "direction": "left" }, { "groups": [ "高台C", "控制", "召唤", "术师", "狙击", "辅助", "其他高台" ], - "location": [ 8, 7 ], + "location": [ 7, 6 ], "direction": "up" }, { "groups": [ "高台C", "控制", "召唤", "术师", "狙击", "辅助", "其他高台" ], - "location": [ 8, 6 ], + "location": [ 7, 7 ], "direction": "up" }, { "groups": [ "地刺", "地面C", "挡人先锋", "其他地面" ], "location": [ 7, 4 ], "direction": "left" + }, + { + "groups": [ "百嘉", "基石", "地面C", "挡人先锋", "重装", "其他地面", "号角", "异德", "刺客" ], + "location": [ 9, 5 ], + "direction": "left" } ] }, @@ -3647,7 +3666,7 @@ { "groups": [ "高台C", "控制", "狙击", "术师", "召唤", "辅助", "其他高台" ], "location": [ 6, 3 ], - "direction": "up" + "direction": "left" }, { "groups": [ "单奶", "群奶" ], diff --git a/resource/roguelike/recruitment.json b/resource/roguelike/recruitment.json index 4550a49890..d1c4327bae 100644 --- a/resource/roguelike/recruitment.json +++ b/resource/roguelike/recruitment.json @@ -43,7 +43,7 @@ "threshold": 1 }, { - "groups": [ "重装", "刺客" ], + "groups": [ "刺客", "重装" ], "threshold": 1 }, { @@ -151,7 +151,7 @@ { "groups": [ "百嘉", "基石", "召唤", "号角", "地面C" ], "threshold": 1, - "offset": -300 + "offset": -400 } ] }, @@ -165,7 +165,7 @@ { "groups": [ "百嘉", "基石", "召唤", "号角", "地面C" ], "threshold": 1, - "offset": -300 + "offset": -400 } ] }, @@ -179,7 +179,7 @@ { "groups": [ "百嘉", "基石", "召唤", "号角", "地面C" ], "threshold": 1, - "offset": -300 + "offset": -400 } ] }, @@ -193,14 +193,13 @@ { "groups": [ "百嘉", "基石", "召唤", "号角", "地面C" ], "threshold": 1, - "offset": -300 + "offset": -400 } ] }, { "name": "Mon3tr", - "Doc": "召唤物虽然不被招募,但也需要在作战中找到自己的group", - "skill": 0 + "Doc": "召唤物虽然不被招募,但也需要在作战中找到自己的group" } ] }, @@ -234,32 +233,17 @@ } ] }, - { - "name": "凯尔希", - "skill": 2, - "recruit_priority": 770, - "promote_priority": 700, - "is_key": true, - "is_start": true, - "recruit_priority_offsets": [ - { - "groups": [ "百嘉", "基石", "召唤", "号角", "地面C", "玛恩纳" ], - "threshold": 2, - "offset": -400 - } - ] - }, { "name": "令", "skill": 1, - "recruit_priority": 680, + "recruit_priority": 620, "promote_priority": 600, "is_start": true, "recruit_priority_offsets": [ { "groups": [ "百嘉", "基石", "召唤", "号角", "地面C" ], "threshold": 1, - "offset": -300 + "offset": -400 } ] }, @@ -314,8 +298,8 @@ "promote_priority": 999, "recruit_priority_offsets": [ { - "groups": [ "玛恩纳", "控制", "刺客" ], - "threshold": 3, + "groups": [ "控制", "刺客" ], + "threshold": 2, "offset": -200 } ] @@ -349,7 +333,7 @@ "recruit_priority_offsets": [ { "groups": [ "高台C", "玛恩纳", "号角" ], - "threshold": 2, + "threshold": 3, "offset": -200 } ] @@ -426,7 +410,7 @@ "name": "仇白", "skill": 3, "alternate_skill": 2, - "recruit_priority": 800, + "recruit_priority": 705, "promote_priority": 899, "is_start": true, "recruit_priority_offsets": [ @@ -469,7 +453,7 @@ { "name": "煌", "skill": 2, - "recruit_priority": 708, + "recruit_priority": 701, "promote_priority": 500, "is_start": true, "recruit_priority_offsets": [ @@ -480,6 +464,112 @@ } ] }, + { + "name": "银灰", + "skill": 3, + "alternate_skill": 1, + "recruit_priority": 620, + "promote_priority": 870, + "is_start": true, + "recruit_priority_offsets": [ + { + "groups": [ "百嘉", "基石", "玛恩纳", "号角", "地面C" ], + "threshold": 2, + "offset": -300 + } + ] + }, + { + "name": "艾丽妮", + "skill": 3, + "alternate_skill": 1, + "recruit_priority": 520, + "promote_priority": 875, + "is_start": true, + "recruit_priority_offsets": [ + { + "groups": [ "百嘉", "基石", "玛恩纳", "号角", "地面C" ], + "threshold": 2, + "offset": -300 + } + ] + }, + { + "name": "史尔特尔", + "skill": 3, + "alternate_skill": 2, + "recruit_priority": 602, + "promote_priority": 920, + "recruit_priority_offsets": [ + { + "groups": [ "百嘉", "基石", "玛恩纳", "号角", "地面C" ], + "threshold": 2, + "offset": -300 + } + ] + }, + { + "name": "芳汀", + "skill": 2, + "recruit_priority": 402 + }, + { + "name": "断崖", + "skill": 2, + "recruit_priority": 370 + }, + { + "name": "刻刀", + "skill": 2, + "recruit_priority": 405 + }, + { + "name": "柏喙", + "skill": 2, + "recruit_priority": 405 + }, + { + "name": "铸铁", + "skill": 2, + "recruit_priority": 305 + }, + { + "name": "布洛卡", + "skill": 2, + "recruit_priority": 412 + }, + { + "name": "星极", + "skill": 2, + "recruit_priority": 411 + }, + { + "name": "泡普卡", + "skill": 2, + "recruit_priority": 460, + "is_key": true + }, + { + "name": "月见夜", + "skill": 2, + "recruit_priority": 466, + "is_key": true + }, + { + "name": "拉普兰德", + "skill": 2, + "recruit_priority": 440 + }, + { + "name": "艾斯黛尔", + "skill": 2, + "recruit_priority": 320 + }, + { + "name": "霜叶", + "skill": 2, + "recruit_priority": 318 + }, { "name": "阿米娅-WARRIOR", "skill": 1, @@ -554,7 +644,7 @@ "name": "灵知", "skill": 1, "is_key": true, - "recruit_priority": 830, + "recruit_priority": 633, "promote_priority": 790, "recruit_priority_offsets": [ { @@ -568,6 +658,7 @@ "name": "寒芒克洛丝", "skill": 2, "is_key": true, + "is_start": true, "recruit_priority": 920, "promote_priority": 591, "recruit_priority_offsets": [ @@ -638,6 +729,21 @@ } ] }, + { + "name": "凯尔希", + "skill": 2, + "recruit_priority": 770, + "promote_priority": 700, + "is_key": true, + "is_start": true, + "recruit_priority_offsets": [ + { + "groups": [ "百嘉", "基石", "召唤", "号角", "地面C", "玛恩纳" ], + "threshold": 2, + "offset": -400 + } + ] + }, { "name": "桑葚", "skill": 2, @@ -680,6 +786,20 @@ } ] }, + { + "name": "絮雨", + "skill": 3, + "alternate_skill": 1, + "recruit_priority": 722, + "promote_priority": 410, + "recruit_priority_offsets": [ + { + "groups": [ "单奶", "群奶" ], + "threshold": 2, + "offset": -300 + } + ] + }, { "name": "华法琳", "skill": 1, @@ -809,6 +929,24 @@ "recruit_priority": 405, "promote_priority": 0, "is_alternate": true + }, + { + "name": "末药" + }, + { + "name": "嘉维尔" + }, + { + "name": "图耶" + }, + { + "name": "亚叶" + }, + { + "name": "锡兰" + }, + { + "name": "闪灵" } ] }, @@ -993,7 +1131,7 @@ { "name": "翎羽", "skill": 1, - "recruit_priority": 510, + "recruit_priority": 310, "promote_priority": 0, "recruit_priority_offsets": [ { @@ -1002,6 +1140,33 @@ "offset": -300 } ] + }, + { + "name": "讯使" + }, + { + "name": "清道夫" + }, + { + "name": "贾维" + }, + { + "name": "推进之王" + }, + { + "name": "嵯峨" + }, + { + "name": "凛冬" + }, + { + "name": "格拉尼" + }, + { + "name": "苇草" + }, + { + "name": "野鬃" } ] }, @@ -1024,12 +1189,12 @@ "name": "麒麟X夜刀", "skill": 2, "is_key": true, - "recruit_priority": 888, + "recruit_priority": 911, "promote_priority": 955, "recruit_priority_offsets": [ { "groups": [ "异德", "刺客" ], - "threshold": 2, + "threshold": 3, "offset": -100 } ] @@ -1074,6 +1239,21 @@ } ] }, + { + "name": "伊内丝", + "skill": 3, + "alternate_skill": 2, + "recruit_priority": 709, + "promote_priority": 830, + "is_key": true, + "recruit_priority_offsets": [ + { + "groups": [ "异德", "刺客" ], + "threshold": 1, + "offset": -200 + } + ] + }, { "name": "傀影", "skill": 2, @@ -1368,7 +1548,6 @@ "skill": 0, "recruit_priority": 460, "promote_priority": 0, - "recruit_priority_when_team_full": 0, "is_alternate": true }, { @@ -1385,6 +1564,27 @@ "offset": 282 } ] + }, + { + "name": "泡泡" + }, + { + "name": "角峰" + }, + { + "name": "可颂" + }, + { + "name": "拜松" + }, + { + "name": "闪击" + }, + { + "name": "吽" + }, + { + "name": "暴雨" } ] }, @@ -1424,7 +1624,6 @@ "skill": 0, "recruit_priority": 305, "promote_priority": 0, - "recruit_priority_when_team_full": 0, "is_alternate": true }, { @@ -1611,7 +1810,7 @@ { "name": "黑角", "skill": 0, - "recruit_priority": 561, + "recruit_priority": 361, "promote_priority": 0, "is_key": true, "recruit_priority_offsets": [ @@ -1672,8 +1871,7 @@ "promote_priority": 0 }, { - "name": "“打字机”", - "skill": 0 + "name": "“打字机”" } ] } diff --git a/resource/roguelike/stage_encounter.json b/resource/roguelike/stage_encounter.json index 256ad427da..930dc22223 100644 --- a/resource/roguelike/stage_encounter.json +++ b/resource/roguelike/stage_encounter.json @@ -168,6 +168,14 @@ "option_num": 4, "choose": 4 }, + "深蓝仪式": { + "option_num": 2, + "choose": 2 + }, + "升华": { + "option_num": 3, + "choose": 1 + }, "赞歌": { "option_num": 1, "choose": 1 @@ -367,4 +375,4 @@ "choose": 1 } } -} \ No newline at end of file +} diff --git a/resource/tasks.json b/resource/tasks.json index e298e9251a..eb7e265767 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -7248,6 +7248,16 @@ "Roguelike@ChooseOper" ] }, + "Roguelike@TempRecruitFlag": { + "action": "DoNothing", + "roi": [ + 587, + 76, + 100, + 20 + ], + "templThreshold": 0.5 + }, "Roguelike@ClickToDrops": { "algorithm": "JustReturn", "action": "ClickRect", diff --git a/resource/template/Roguelike@TempRecruitFlag.png b/resource/template/Roguelike@TempRecruitFlag.png new file mode 100644 index 0000000000..3252518d37 Binary files /dev/null and b/resource/template/Roguelike@TempRecruitFlag.png differ diff --git a/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.cpp b/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.cpp index 93d7d915de..c0105ef3e8 100644 --- a/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.cpp +++ b/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.cpp @@ -6,15 +6,18 @@ #include const asst::RoguelikeOperInfo& asst::RoguelikeRecruitConfig::get_oper_info(const std::string& theme, - const std::string& name) const noexcept + const std::string& name) noexcept { auto& opers = m_all_opers.at(theme); - if (auto find_iter = opers.find(name); find_iter != opers.cend()) { - return find_iter->second; + if (opers.contains(name)) { + return opers.at(name); } else { - static RoguelikeOperInfo empty; - return empty; + RoguelikeOperInfo info; + info.name = name; + info.group_id = get_group_id(theme, name); + opers.emplace(name, std::move(info)); + return opers.at(name); } } @@ -85,8 +88,8 @@ bool asst::RoguelikeRecruitConfig::parse(const json::value& json) info.recruit_priority = oper_info.get("recruit_priority", 0); info.promote_priority = oper_info.get("promote_priority", 0); info.is_alternate = oper_info.get("is_alternate", false); - info.skill = oper_info.at("skill").as_integer(); - info.alternate_skill = oper_info.get("alternate_skill", 0); + info.skill = oper_info.get("skill", 1); + info.alternate_skill = oper_info.get("alternate_skill", 1); info.skill_usage = static_cast(oper_info.get("skill_usage", 1)); info.alternate_skill_usage = static_cast(oper_info.get("alternate_skill_usage", 1)); diff --git a/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.h b/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.h index 59eca65fdc..56b12f12be 100644 --- a/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.h +++ b/src/MaaCore/Config/Roguelike/RoguelikeRecruitConfig.h @@ -23,7 +23,7 @@ namespace asst struct RoguelikeOperInfo { std::string name; - int group_id; // 干员组id + int group_id = 0; // 干员组id int recruit_priority = 0; // 招募优先级 (0-1000) int promote_priority = 0; // 晋升优先级 (0-1000) int recruit_priority_when_team_full = 0; // 队伍满时的招募优先级 (0-1000) @@ -34,7 +34,7 @@ namespace asst bool is_start = false; // 是否为开局干员 std::vector recruit_priority_offsets; bool is_alternate = false; // 是否后备干员 (允许重复招募、划到后备干员时不再往右划动) - int skill = 0; + int skill = 1; int alternate_skill = 0; battle::SkillUsage skill_usage = battle::SkillUsage::Possibly; battle::SkillUsage alternate_skill_usage = battle::SkillUsage::Possibly; @@ -45,7 +45,7 @@ namespace asst public: virtual ~RoguelikeRecruitConfig() override = default; - const RoguelikeOperInfo& get_oper_info(const std::string& theme, const std::string& name) const noexcept; + const RoguelikeOperInfo& get_oper_info(const std::string& theme, const std::string& name) noexcept; const std::vector> get_role_info(const std::string& theme, const battle::Role& role) const noexcept; // [deprecated] const std::vector get_group_info(const std::string& theme) const noexcept; diff --git a/src/MaaCore/Task/Roguelike/RoguelikeRecruitTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeRecruitTaskPlugin.cpp index d2ab70fffc..7540b01030 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeRecruitTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeRecruitTaskPlugin.cpp @@ -9,6 +9,7 @@ #include "Utils/Logger.hpp" #include "Utils/NoWarningCV.h" #include "Vision/OcrImageAnalyzer.h" +#include "Vision/MatchImageAnalyzer.h" #include "Vision/Roguelike/RoguelikeRecruitImageAnalyzer.h" #include "Vision/Roguelike/RoguelikeRecruitSupportAnalyzer.h" @@ -160,12 +161,19 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() // 开始识别前先往前翻两页,是方舟的bug,有可能进招募界面时不是从最左边开始 swipe_to_the_left_of_operlist(); + bool temp_recruit_exist = false; // 检测是否存在临时招募 + auto image = ctrler()->get_image(); + MatchImageAnalyzer temp_recruit_analyzer(image); + temp_recruit_analyzer.set_task_info("Roguelike@TempRecruitFlag"); + temp_recruit_exist = temp_recruit_analyzer.analyze(); + Log.trace(__FUNCTION__, "temp_recruit_exist", temp_recruit_exist); + // 翻页找出所有候选干员 for (; i != SwipeTimes; ++i) { if (need_exit()) { return false; } - auto image = ctrler()->get_image(); + image = ctrler()->get_image(); RoguelikeRecruitImageAnalyzer analyzer(image); if (!analyzer.analyze()) { Log.trace(__FUNCTION__, "| Page", i, "recruit list analyse failed"); @@ -183,6 +191,7 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() int max_oper_x = 0; for (const auto& oper_info : oper_list) { + Log.info(__FUNCTION__, "| Operator", oper_info.name); oper_names.emplace(oper_info.name); max_oper_x = std::max(max_oper_x, oper_info.rect.x); @@ -209,10 +218,6 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() // 查询招募配置 auto& recruit_info = RoguelikeRecruit.get_oper_info(rogue_theme, oper_info.name); - if (recruit_info.name.empty()) { - continue; - } - int priority = 0; // 查询编队是否已持有该干员 @@ -228,6 +233,10 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() // 干员待晋升 priority = team_full_without_rookie ? recruit_info.promote_priority_when_team_full : recruit_info.promote_priority; + if (temp_recruit_exist) { // 临时招募干员的进阶优先级略微提高 + priority += 150; + temp_recruit_exist = false; + } } } else { @@ -250,6 +259,11 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() oper_info.level); } + if (temp_recruit_exist) { // 临时招募干员具有极高抓取优先级 + priority += 1800; + temp_recruit_exist = false; + } + if (!recruit_info.is_alternate) { // __________________will-be-removed-begin__________________ const battle::Role oper_role = get_oper_role(oper_info.name); @@ -348,7 +362,7 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() swipe_to_the_left_of_operlist(i + 1); } - auto image = ctrler()->get_image(); + image = ctrler()->get_image(); RoguelikeRecruitImageAnalyzer analyzer(image); if (!analyzer.analyze()) { Log.error(__FUNCTION__, "| Random recruitment analyse failed"); diff --git a/src/MaaCore/Vision/Roguelike/RoguelikeRecruitImageAnalyzer.cpp b/src/MaaCore/Vision/Roguelike/RoguelikeRecruitImageAnalyzer.cpp index ccb6cf68af..f89adb028b 100644 --- a/src/MaaCore/Vision/Roguelike/RoguelikeRecruitImageAnalyzer.cpp +++ b/src/MaaCore/Vision/Roguelike/RoguelikeRecruitImageAnalyzer.cpp @@ -28,6 +28,7 @@ bool asst::RoguelikeRecruitImageAnalyzer::analyze() cv::merge(std::array { blue, blue, blue }, bbb_image); } + analyzer.sort_result_vertical(); for (const auto& [_, rect, name] : analyzer.get_result()) { int elite = match_elite(rect); int level = match_level(bbb_image, rect);