From d4e1a32199c8a9b0fda652143000f21a5cc32d93 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sat, 18 Jun 2022 22:58:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E8=82=89=E9=B8=BD=20?= =?UTF-8?q?copilot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/肉鸽战斗流程协议.md | 77 ++------ resource/roguelike/Accident.json | 28 --- resource/roguelike_copilot.json | 20 ++ resource/roguelike_recruit.json | 172 +++++++++--------- src/MeoAssistant/AsstBattleDef.h | 14 +- src/MeoAssistant/Resource.cpp | 18 +- .../RoguelikeBattleTaskPlugin.cpp | 84 ++++++++- src/MeoAssistant/RoguelikeBattleTaskPlugin.h | 4 + src/MeoAssistant/RoguelikeCopilotConfiger.cpp | 170 +++-------------- src/MeoAssistant/RoguelikeCopilotConfiger.h | 13 +- .../RoguelikeRecruitTaskPlugin.cpp | 16 +- 11 files changed, 256 insertions(+), 360 deletions(-) delete mode 100644 resource/roguelike/Accident.json create mode 100644 resource/roguelike_copilot.json diff --git a/docs/肉鸽战斗流程协议.md b/docs/肉鸽战斗流程协议.md index 2f643213ac..cd4d339d76 100644 --- a/docs/肉鸽战斗流程协议.md +++ b/docs/肉鸽战斗流程协议.md @@ -1,65 +1,26 @@ # 肉鸽战斗流程协议 -`resource/roguelike/*.json` 的使用方法及各字段说明 +`resource/roguelike_copilot.json` 的使用方法及各字段说明 ## 完整字段一览 ```jsonc -{ - "stage_name": "驯兽小屋", // 关卡名,必选 - "actions": [ // 战斗中的操作。有序,执行完前一个才会去执行下一个。必选 - { - "type": "部署", // 操作类型,可选,默认 "Deploy" - // "Deploy" | "Skill" | "Retreat" | "AllSkill" - // "部署" | "技能" | "撤退" | "全部技能" - // 中英文皆可,效果相同 - // 若为 "部署", 当费用不够时,会一直等待到费用够 - // 若为 "技能", 当技能 cd 没转好时,会直接跳过当前项。 - // 考虑不同干员技能效果及 cd 差异巨大,谨慎使用(例如 山 2 技能 这种,假如已经开了,你又开一次,就给关了) - // "全部技能", 会一次性使用所有 skill_usgae == 3 的干员的技能 - - "kills": 0, // 击杀数条件,如果没达到就一直等待。可选,默认为 0。直接执行 - // TODO: 其他条件 - // TODO: "condition_type": 0, // 执行条件间的关系,可选,默认 0 - // // 0 - 且; 1 - 或 - - "roles": [ // 该位置使用的职业。可选,默认为空,任何职业都可以 - // 有序,会先使用靠前的职业 - // 会根据位置类型自动区分是高台还是地面。若设置了不可放置的职业,则忽略该职业 - // 如果这里面的职业一个都没有,则会跳过该位置转而执行下一条 - "近卫", - "先锋", - "重装", - "召唤物" - ], - - "waiting_cost": false, // 如果有 roles 中有靠前的职业,但费用不够,是否等待。可选,默认 false - // 为 true 时,会使用 roles 中,当前有的、最靠前的职业(一直等他费用够) - // 为 false 时,会使用 roles 中,当前有的、费用够的中最靠前的职业 - - "location": [ 5, 5 ], // 操作的干员的位置。必选 - - "direction": "左", // 部署干员的干员朝向。 type 为 "部署" 时必选 - // "Left" | "Right" | "Up" | "Down" | "None" - // "左" | "右" | "上" | "下" | "无" - // 中英文皆可,效果相同 - - "pre_delay": 0, // 前置延时。可选,默认 0, 单位毫秒 - "rear_delay": 0, // 后置延时。可选,默认 0, 单位毫秒 - - "timeout": 999999999 // 超时时间。当 type 为 "部署" 时可选。默认 INT_MAX, 单位毫秒 - // 等待超时则放弃当前动作, 转而执行下一个动作 - }, - { // 简单举例 - "location": [6, 6], - "roles": [ - "近卫", - "先锋", - "重装", - "召唤物" - ], - "direction": "左" - } - ] -} +[ + { + "stage_name": "驯兽小屋", // 关卡名,必选 + "replacement_home": [ // 替换掉家门的位置,可选,默认为空 + [ 2, 8 ] // 会使用这里面的坐标来代替蓝门的坐标,然后堵门 + ], + "key_kills": [ // 关键击杀数,可选,默认为空 + 15, // 若不为空,干员技能会攒着,不是好了就放,而是等到击杀数达到时再释放 + ... // 当跑完数组里所有的元素之后,再把干员技能变成好了就放 + ] + }, + { + "stage_name": "巡逻队", + "replacement_home": [ + [ 2, 8 ] + ] + } +] ``` diff --git a/resource/roguelike/Accident.json b/resource/roguelike/Accident.json deleted file mode 100644 index 6bc59c6a9d..0000000000 --- a/resource/roguelike/Accident.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "stage_name": "意外", - "actions": [ - { - "location": [ - 5, - 3 - ], - "roles": [ - "近卫", - "先锋", - "重装", - "召唤物" - ], - "direction": "左" - }, - { - "location": [ - 5, - 2 - ], - "roles": [ - "辅助" - ], - "direction": "左" - } - ] -} diff --git a/resource/roguelike_copilot.json b/resource/roguelike_copilot.json new file mode 100644 index 0000000000..8c56b02921 --- /dev/null +++ b/resource/roguelike_copilot.json @@ -0,0 +1,20 @@ +[ + { + "stage_name": "驯兽小屋", + "replacement_home": [ + [ + 8, + 3 + ] + ] + }, + { + "stage_name": "巡逻队", + "replacement_home": [ + [ + 8, + 3 + ] + ] + } +] diff --git a/resource/roguelike_recruit.json b/resource/roguelike_recruit.json index 145dc33263..975ca7b969 100644 --- a/resource/roguelike_recruit.json +++ b/resource/roguelike_recruit.json @@ -37,11 +37,32 @@ "level": 5, "skill": 1 }, + { + "name": "陈", + "level": 6, + "skill": 2 + }, + { + "name": "拉普兰德", + "level": 5, + "skill": 2 + }, + { + "name": "阿米娅", + "level": 5, + "skill": 1 + }, { "name": "史尔特尔", "level": 6, "skill": 2 }, + { + "name": "银灰", + "level": 6, + "skill": 3, + "alternate_skill": 1 + }, { "name": "赫拉格", "level": 6, @@ -53,7 +74,7 @@ "skill": 1 }, { - "name": "拉普兰德", + "name": "幽灵鲨", "level": 5, "skill": 2 }, @@ -62,27 +83,11 @@ "level": 4, "skill": 1 }, - { - "name": "陈", - "level": 6, - "skill": 2 - }, { "name": "斯卡蒂", "level": 6, "skill": 1 }, - { - "name": "阿米娅", - "level": 5, - "skill": 1 - }, - { - "name": "银灰", - "level": 6, - "skill": 3, - "alternate_skill": 1 - }, { "name": "Sharp", "level": 5, @@ -94,7 +99,7 @@ "skill": 1 }, { - "name": "幽灵鲨", + "name": "星极", "level": 5, "skill": 2 }, @@ -105,9 +110,9 @@ "alternate_skill": 2 }, { - "name": "断罪者", - "level": 4, - "skill": 1 + "name": "柏喙", + "level": 5, + "skill": 2 }, { "name": "芳汀", @@ -115,9 +120,9 @@ "skill": 2 }, { - "name": "星极", - "level": 5, - "skill": 2 + "name": "断罪者", + "level": 4, + "skill": 1 }, { "name": "战车", @@ -204,11 +209,6 @@ "level": 5, "skill": 2 }, - { - "name": "柏喙", - "level": 5, - "skill": 2 - }, { "name": "布洛卡", "level": 5, @@ -246,11 +246,6 @@ } ], "Pioneer": [ - { - "name": "芬", - "level": 3, - "skill": 1 - }, { "name": "风笛", "level": 6, @@ -287,6 +282,11 @@ "level": 5, "skill": 2 }, + { + "name": "芬", + "level": 3, + "skill": 1 + }, { "name": "清道夫", "level": 4, @@ -307,6 +307,21 @@ "level": 4, "skill": 1 }, + { + "name": "红豆", + "level": 4, + "skill": 2 + }, + { + "name": "苇草", + "level": 5, + "skill": 1 + }, + { + "name": "格拉尼", + "level": 5, + "skill": 1 + }, { "name": "琴柳", "level": 6, @@ -341,21 +356,6 @@ "name": "翎羽", "level": 3, "skill": 1 - }, - { - "name": "红豆", - "level": 4, - "skill": 2 - }, - { - "name": "苇草", - "level": 5, - "skill": 1 - }, - { - "name": "格拉尼", - "level": 5, - "skill": 1 } ], "Tank": [ @@ -367,8 +367,17 @@ { "name": "塞雷娅", "level": 6, - "skill": 2, - "alternate_skill": 1 + "skill": 2 + }, + { + "name": "暮落", + "level": 5, + "skill": 2 + }, + { + "name": "星熊", + "level": 6, + "skill": 2 }, { "name": "斑点", @@ -401,11 +410,6 @@ "level": 5, "skill": 1 }, - { - "name": "星熊", - "level": 6, - "skill": 2 - }, { "name": "雷蛇", "level": 5, @@ -461,11 +465,6 @@ "level": 4, "skill": 2 }, - { - "name": "暮落", - "level": 5, - "skill": 2 - }, { "name": "极光", "level": 5, @@ -713,11 +712,6 @@ "level": 6, "skill": 3 }, - { - "name": "伊芙利特", - "level": 6, - "skill": 2 - }, { "name": "阿米娅", "level": 5, @@ -733,6 +727,11 @@ "level": 6, "skill": 1 }, + { + "name": "伊芙利特", + "level": 6, + "skill": 2 + }, { "name": "天火", "level": 5, @@ -998,11 +997,6 @@ } ], "Medic": [ - { - "name": "安赛尔", - "level": 3, - "skill": 1 - }, { "name": "凯尔希", "level": 6, @@ -1090,6 +1084,11 @@ "level": 5, "skill": 1 }, + { + "name": "安赛尔", + "level": 3, + "skill": 1 + }, { "name": "闪灵", "level": 6, @@ -1122,22 +1121,12 @@ } ], "Support": [ - { - "name": "浊心斯卡蒂", - "level": 6, - "skill": 2 - }, { "name": "令", "level": 6, "skill": 3, "alternate_skill": 2 }, - { - "name": "梓兰", - "level": 3, - "skill": 1 - }, { "name": "波登可", "level": 4, @@ -1148,16 +1137,17 @@ "level": 6, "skill": 1 }, - { - "name": "安洁莉娜", - "level": 6, - "skill": 1 - }, { "name": "铃兰", "level": 6, "skill": 2 }, + { + "name": "安洁莉娜", + "level": 6, + "skill": 3, + "alternate_skill": 2 + }, { "name": "巫恋", "level": 5, @@ -1178,6 +1168,16 @@ "level": 5, "skill": 1 }, + { + "name": "梓兰", + "level": 3, + "skill": 1 + }, + { + "name": "浊心斯卡蒂", + "level": 6, + "skill": 2 + }, { "name": "月禾", "level": 5, diff --git a/src/MeoAssistant/AsstBattleDef.h b/src/MeoAssistant/AsstBattleDef.h index 88af5c5bd6..dad10f7b47 100644 --- a/src/MeoAssistant/AsstBattleDef.h +++ b/src/MeoAssistant/AsstBattleDef.h @@ -110,16 +110,10 @@ namespace asst } }; - struct RoguelikeBattleAction + struct RoguelikeBattleData { - int kills = 0; - BattleActionType type = BattleActionType::Deploy; - std::vector roles; - bool waiting_cost = false; - Point location; - BattleDeployDirection direction = BattleDeployDirection::Right; - int pre_delay = 0; - int rear_delay = 0; - int time_out = INT_MAX; + std::string stage_name; + std::vector replacement_home; + std::vector key_kills; }; } diff --git a/src/MeoAssistant/Resource.cpp b/src/MeoAssistant/Resource.cpp index e30502d999..13ef64d208 100644 --- a/src/MeoAssistant/Resource.cpp +++ b/src/MeoAssistant/Resource.cpp @@ -22,7 +22,7 @@ bool asst::Resource::load(const std::string& dir) constexpr static auto InfrastCfgFilename = "infrast.json"; constexpr static auto InfrastTempls = "template/infrast"; //constexpr static const char* CopilotCfgDirname = "copilot"; - constexpr static auto RoguelikeCfgDirname = "roguelike"; + constexpr static auto RoguelikeCfgDirname = "roguelike_copilot.json"; constexpr static auto OcrResourceFilename = "PaddleOCR"; constexpr static auto TilesCalcResourceFilename = "Arknights-Tile-Pos"; constexpr static auto StageDropsCfgFilename = "stages.json"; @@ -91,17 +91,15 @@ bool asst::Resource::load(const std::string& dir) // } //} - if (std::filesystem::exists(dir + RoguelikeCfgDirname)) { - for (const auto& entry : std::filesystem::directory_iterator(dir + RoguelikeCfgDirname)) { - if (entry.path().extension() != ".json") { - continue; - } - if (!m_roguelike_cfg_unique_ins.load(entry.path().string())) { - m_last_error = entry.path().string() + " Load failed"; - return false; - } + if (!m_roguelike_cfg_unique_ins.load(dir + RoguelikeCfgDirname)) { + if (!m_loaded) { + m_last_error = std::string(RoguelikeCfgDirname) + ": " + m_roguelike_cfg_unique_ins.get_last_error(); + return false; } } + else { + overload = true; + } if (!m_infrast_cfg_unique_ins.load(dir + InfrastCfgFilename)) { if (!m_loaded) { diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp index 443c396f01..6a465759b8 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp @@ -117,6 +117,40 @@ bool asst::RoguelikeBattleTaskPlugin::get_stage_info() calced = true; } + auto opt = Resrc.roguelike().get_stage_data(m_stage_name); + if (opt && !opt->replacement_home.empty()) { + m_homes = opt->replacement_home; + std::string log_str = "[ "; + for (auto& home : m_homes) { + if (m_normal_tile_info.find(home) == m_normal_tile_info.end()) { + Log.error("No replacement home point", home.x, home.y); + } + log_str += "( " + std::to_string(home.x) + ", " + std::to_string(home.y) + " ), "; + } + log_str += "]"; + Log.info("replacement home:", log_str); + } + else { + for (const auto& [loc, side] : m_normal_tile_info) { + if (side.key == TilePack::TileKey::Home) { + m_homes.emplace_back(loc); + } + } + } + if (opt && !opt->key_kills.empty()) { + std::string log_str = "[ "; + for (const auto& kills : opt->key_kills) { + m_key_kills.emplace(kills); + log_str += std::to_string(kills) + ", "; + } + log_str += "]"; + Log.info("key kills:", log_str); + } + + if (m_homes.empty()) { + Log.error("Unknown home pos"); + } + if (calced) { auto cb_info = basic_info_with_what("StageInfo"); auto& details = cb_info["details"]; @@ -307,10 +341,14 @@ void asst::RoguelikeBattleTaskPlugin::clear() m_opers_used = false; m_pre_hp = 0; m_homes.clear(); + decltype(m_key_kills) empty; + m_key_kills.swap(empty); m_cur_home_index = 0; m_stage_name.clear(); m_side_tile_info.clear(); m_used_tiles.clear(); + m_kills = 0; + m_total_kills = 0; for (auto& [key, status] : m_restore_status) { m_status->set_number(key, status); @@ -320,6 +358,10 @@ void asst::RoguelikeBattleTaskPlugin::clear() bool asst::RoguelikeBattleTaskPlugin::try_possible_skill(const cv::Mat& image) { + if (!check_key_kills(image)) { + return false; + } + auto task_ptr = Task.get("BattleAutoSkillFlag"); const Rect& skill_roi_move = task_ptr->rect_move; @@ -356,6 +398,29 @@ bool asst::RoguelikeBattleTaskPlugin::try_possible_skill(const cv::Mat& image) return used; } +bool asst::RoguelikeBattleTaskPlugin::check_key_kills(const cv::Mat& image) +{ + if (m_key_kills.empty()) { + return true; + } + int need_kills = m_key_kills.front(); + + BattleImageAnalyzer analyzer(image); + if (m_total_kills) { + analyzer.set_pre_total_kills(m_total_kills); + } + analyzer.set_target(BattleImageAnalyzer::Target::Kills); + if (analyzer.analyze()) { + m_kills = analyzer.get_kills(); + m_total_kills = analyzer.get_total_kills(); + if (m_kills >= need_kills) { + m_key_kills.pop(); + return true; + } + } + return false; +} + bool asst::RoguelikeBattleTaskPlugin::wait_start() { auto start_time = std::chrono::system_clock::now(); @@ -392,6 +457,15 @@ bool asst::RoguelikeBattleTaskPlugin::wait_start() std::string text = "( " + std::to_string(loc.x) + ", " + std::to_string(loc.y) + " )"; cv::putText(image, text, cv::Point(info.pos.x - 30, info.pos.y), 1, 1.2, cv::Scalar(0, 0, 255), 2); } + + // 识别一帧总击杀数 + BattleImageAnalyzer kills_analyzer(image); + kills_analyzer.set_target(BattleImageAnalyzer::Target::Kills); + if (kills_analyzer.analyze()) { + m_kills = kills_analyzer.get_kills(); + m_total_kills = kills_analyzer.get_total_kills(); + } + #ifdef WIN32 cv::imwrite("map/" + utils::utf8_to_ansi(m_stage_name) + ".png", image); #else @@ -449,16 +523,6 @@ asst::RoguelikeBattleTaskPlugin::DeployInfo asst::RoguelikeBattleTaskPlugin::cal break; } - if (m_homes.empty()) { - for (const auto& [loc, side] : m_side_tile_info) { - if (side.key == TilePack::TileKey::Home) { - m_homes.emplace_back(loc); - } - } - if (m_homes.empty()) { - Log.error("Unknown home pos"); - } - } if (m_cur_home_index >= m_homes.size()) { m_cur_home_index = 0; } diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.h b/src/MeoAssistant/RoguelikeBattleTaskPlugin.h index efd52611c1..51fcddb173 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.h +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.h @@ -30,6 +30,7 @@ namespace asst bool retreat(const Point& point); void clear(); bool try_possible_skill(const cv::Mat& image); + bool check_key_kills(const cv::Mat& image); bool wait_start(); struct DeployInfo @@ -46,10 +47,13 @@ namespace asst bool m_opers_used = false; int m_pre_hp = 0; + int m_kills = 0; + int m_total_kills = 0; std::unordered_map m_side_tile_info; std::unordered_map m_normal_tile_info; std::vector m_homes; + std::queue m_key_kills; size_t m_cur_home_index = 0; std::unordered_map m_used_tiles; std::unordered_map m_restore_status; diff --git a/src/MeoAssistant/RoguelikeCopilotConfiger.cpp b/src/MeoAssistant/RoguelikeCopilotConfiger.cpp index e85a85a515..70fdbb433c 100644 --- a/src/MeoAssistant/RoguelikeCopilotConfiger.cpp +++ b/src/MeoAssistant/RoguelikeCopilotConfiger.cpp @@ -4,158 +4,34 @@ #include "Logger.hpp" +std::optional asst::RoguelikeCopilotConfiger::get_stage_data(const std::string& stage_name) const +{ + auto it = m_stage_data.find(stage_name); + if (it == m_stage_data.end()) { + return std::nullopt; + } + return it->second; +} + bool asst::RoguelikeCopilotConfiger::parse(const json::value& json) { - std::string stage_name = json.at("stage_name").as_string(); - - std::vector actions_vec; - - for (const auto& action_info : json.at("actions").as_array()) { - RoguelikeBattleAction action; - - static const std::unordered_map ActionTypeMapping = { - { "Deploy", BattleActionType::Deploy }, - { "DEPLOY", BattleActionType::Deploy }, - { "deploy", BattleActionType::Deploy }, - { "部署", BattleActionType::Deploy }, - - { "Skill", BattleActionType::UseSkill }, - { "SKILL", BattleActionType::UseSkill }, - { "skill", BattleActionType::UseSkill }, - { "技能", BattleActionType::UseSkill }, - - { "Retreat", BattleActionType::Retreat }, - { "RETREAT", BattleActionType::Retreat }, - { "retreat", BattleActionType::Retreat }, - { "撤退", BattleActionType::Retreat }, - - { "AllSkill", BattleActionType::UseAllSkill }, - { "allskill", BattleActionType::UseAllSkill }, - { "ALLSKILL", BattleActionType::UseAllSkill }, - { "Allskill", BattleActionType::UseAllSkill }, - { "全部技能", BattleActionType::UseAllSkill }, - }; - - std::string type_str = action_info.get("type", "Deploy"); - - if (auto iter = ActionTypeMapping.find(type_str); - iter != ActionTypeMapping.end()) { - action.type = iter->second; - } - else { - action.type = BattleActionType::Deploy; - } - action.kills = action_info.get("kills", 0); - - if (action_info.contains("roles")) { - for (const auto& role_info : action_info.at("roles").as_array()) { - static const std::unordered_map RoleMapping = { - { "MEDIC", BattleRole::Medic }, - { "Medic", BattleRole::Medic }, - { "medic", BattleRole::Medic }, - { "医疗", BattleRole::Medic }, - - { "WARRIOR", BattleRole::Warrior }, - { "Warrior", BattleRole::Warrior }, - { "warrior", BattleRole::Warrior }, - { "近卫", BattleRole::Warrior }, - - { "SPECIAL", BattleRole::Special }, - { "Special", BattleRole::Special }, - { "special", BattleRole::Special }, - { "特种", BattleRole::Special }, - - { "SNIPER", BattleRole::Sniper }, - { "Sniper", BattleRole::Sniper }, - { "sniper", BattleRole::Sniper }, - { "狙击", BattleRole::Sniper }, - - { "PIONEER", BattleRole::Pioneer }, - { "Pioneer", BattleRole::Pioneer }, - { "pioneer", BattleRole::Pioneer }, - { "先锋", BattleRole::Pioneer }, - - { "TANK", BattleRole::Tank }, - { "Tank", BattleRole::Tank }, - { "tank", BattleRole::Tank }, - { "重装", BattleRole::Tank }, - - { "SUPPORT", BattleRole::Support }, - { "Support", BattleRole::Support }, - { "support", BattleRole::Support }, - { "辅助", BattleRole::Support }, - - { "CASTER", BattleRole::Caster }, - { "Caster", BattleRole::Caster }, - { "caster", BattleRole::Caster }, - { "术师", BattleRole::Caster }, - - { "Drone", BattleRole::Drone }, - { "DRONE", BattleRole::Drone }, - { "drone", BattleRole::Drone }, - { "召唤物", BattleRole::Drone }, - { "无人机", BattleRole::Drone } - }; - - std::string role_name = role_info.as_string(); - if (auto iter = RoleMapping.find(role_name); - iter != RoleMapping.end()) { - action.roles.emplace_back(iter->second); - } - else { - Log.error("Unknown role", role_name); - } + for (const auto& stage_info : json.as_array()) { + std::string stage_name = stage_info.at("stage_name").as_string(); + RoguelikeBattleData data; + data.stage_name = stage_name; + if (stage_info.contains("replacement_home")) { + for (const auto& points : stage_info.at("replacement_home").as_array()) { + const auto& points_array = points.as_array(); + Point point(points_array.at(0).as_integer(), points_array.at(1).as_integer()); + data.replacement_home.push_back(point); } } - - action.location.x = action_info.get("location", 0, 0); - action.location.y = action_info.get("location", 1, 0); - - static const std::unordered_map DeployDirectionMapping = { - { "Right", BattleDeployDirection::Right }, - { "RIGHT", BattleDeployDirection::Right }, - { "right", BattleDeployDirection::Right }, - { "右", BattleDeployDirection::Right }, - - { "Left", BattleDeployDirection::Left }, - { "LEFT", BattleDeployDirection::Left }, - { "left", BattleDeployDirection::Left }, - { "左", BattleDeployDirection::Left }, - - { "Up", BattleDeployDirection::Up }, - { "UP", BattleDeployDirection::Up }, - { "up", BattleDeployDirection::Up }, - { "上", BattleDeployDirection::Up }, - - { "Down", BattleDeployDirection::Down }, - { "DOWN", BattleDeployDirection::Down }, - { "down", BattleDeployDirection::Down }, - { "下", BattleDeployDirection::Down }, - - { "None", BattleDeployDirection::None }, - { "NONE", BattleDeployDirection::None }, - { "none", BattleDeployDirection::None }, - { "无", BattleDeployDirection::None }, - }; - - std::string direction_str = action_info.get("direction", "Right"); - - if (auto iter = DeployDirectionMapping.find(direction_str); - iter != DeployDirectionMapping.end()) { - action.direction = iter->second; + if (stage_info.contains("key_kills")) { + for (const auto& key_kill : stage_info.at("key_kills").as_array()) { + data.key_kills.emplace_back(key_kill.as_integer()); + } } - else { - action.direction = BattleDeployDirection::Right; - } - action.waiting_cost = action_info.get("waiting_cost", false); - action.pre_delay = action_info.get("pre_delay", 0); - action.rear_delay = action_info.get("rear_delay", 0); - action.time_out = action_info.get("timeout", INT_MAX); - - actions_vec.emplace_back(std::move(action)); + m_stage_data.emplace(std::move(stage_name), std::move(data)); } - - m_battle_actions[std::move(stage_name)] = std::move(actions_vec); - return true; } diff --git a/src/MeoAssistant/RoguelikeCopilotConfiger.h b/src/MeoAssistant/RoguelikeCopilotConfiger.h index 6b8ff714e2..4b5842b8f7 100644 --- a/src/MeoAssistant/RoguelikeCopilotConfiger.h +++ b/src/MeoAssistant/RoguelikeCopilotConfiger.h @@ -1,6 +1,8 @@ #pragma once #include "AbstractConfiger.h" +#include + #include "AsstBattleDef.h" namespace asst @@ -10,17 +12,10 @@ namespace asst public: virtual ~RoguelikeCopilotConfiger() = default; - bool contains_actions(const std::string& stage_name) const noexcept - { - return m_battle_actions.find(stage_name) != m_battle_actions.cend(); - } + std::optional get_stage_data(const std::string& stage_name) const; - auto get_actions(const std::string& stage_name) const noexcept - { - return m_battle_actions.at(stage_name); - } protected: virtual bool parse(const json::value& json) override; - std::unordered_map> m_battle_actions; + std::unordered_map m_stage_data; }; } diff --git a/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp b/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp index c25f7122f8..a82ab30008 100644 --- a/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp +++ b/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp @@ -40,14 +40,26 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() }; for (const auto& info : analyzer.get_result()) { - if (info.elite == 0 || - (info.elite == 1 && info.level < 50)) { + // 先看看有没有精二的 + if (info.elite != 2) { continue; } recruit_oper(info); break; } + if (!recruited) { + for (const auto& info : analyzer.get_result()) { + // 拿个精一 50 以上的 + if (info.elite == 0 || + (info.elite == 1 && info.level < 50)) { + continue; + } + recruit_oper(info); + break; + } + } + if (!recruited) { Log.info("All are lower"); // 随便招个精一的