From d4dc680dcc897fa097ef672c387cb60e3f7bf93c Mon Sep 17 00:00:00 2001 From: DavidWang19 Date: Wed, 26 Oct 2022 18:53:53 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E9=98=9F=E4=BC=8D=E5=86=85=E5=B7=B2=E6=9C=89=E5=90=8C=E8=81=8C?= =?UTF-8?q?=E4=B8=9A=E5=B9=B2=E5=91=98=E6=95=B0=E9=87=8F=E5=86=B3=E5=AE=9A?= =?UTF-8?q?=E6=8B=9B=E5=8B=9F=E6=9D=83=E9=87=8D=E7=9A=84=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/roguelike_recruit.json | 118 +++++++++++++++--- .../Resource/RoguelikeCopilotConfiger.cpp | 49 ++------ .../Resource/RoguelikeRecruitConfiger.cpp | 6 + .../Resource/RoguelikeRecruitConfiger.h | 1 + src/MeoAssistant/RuntimeStatus.h | 1 + .../Plugin/RoguelikeRecruitTaskPlugin.cpp | 30 ++++- .../Task/Plugin/RoguelikeRecruitTaskPlugin.h | 1 + .../Task/Plugin/RoguelikeResetTaskPlugin.cpp | 2 +- src/MeoAssistant/Utils/AsstBattleDef.h | 58 +++++++++ 9 files changed, 212 insertions(+), 54 deletions(-) diff --git a/resource/roguelike_recruit.json b/resource/roguelike_recruit.json index 8cf6f19524..85b9b820f4 100644 --- a/resource/roguelike_recruit.json +++ b/resource/roguelike_recruit.json @@ -20,21 +20,53 @@ "promote_priority": 650, "promote_priority_when_team_full": 750, "promote_priority_when_team_full_Doc": "不填默认 promote_priority + 100", - "Doc": "编队满了且编队内所有干员 promote_priority 均大于200,才会走两个 when_team_full 的逻辑" + "Doc": "编队满了且编队内所有干员 promote_priority 均大于200,才会走两个 when_team_full 的逻辑", + "recruit_priority_offset": [ + [ + 100, + 100 + ], + [ + 200, + -200 + ] + ], + "offset_doc": "队伍内已有100人同职业则权重+100,200人-200,已有数量从小到大" }, { "name": "海沫", "skill": 1, - "recruit_priority": 960, + "recruit_priority": 500, "promote_priority": 650, - "promote_priority_when_team_full": 750 + "promote_priority_when_team_full": 750, + "recruit_priority_offset": [ + [ + 0, + 600 + ], + [ + 2, + -500 + ] + ] }, { "name": "羽毛笔", "skill": 1, - "recruit_priority": 950, + "recruit_priority": 490, "promote_priority": 650, - "promote_priority_when_team_full": 750 + "promote_priority_when_team_full": 750, + "recruit_priority_offset": [ + [ + 0, + 600 + ], + [ + 2, + -490 + ] + ] + }, { "name": "百炼嘉维尔", @@ -47,17 +79,37 @@ "name": "棘刺", "skill": 3, "alternate_skill": 1, - "recruit_priority": 780, + "recruit_priority": 800, "promote_priority": 1000, - "promote_priority_when_team_full": 1200 + "promote_priority_when_team_full": 1200, + "recruit_priority_offset": [ + [ + 1, + -780 + ], + [ + 2, + 200 + ] + ] }, { "name": "山", "skill": 2, "skill_usage": 2, - "recruit_priority": 750, + "recruit_priority": 400, "promote_priority": 550, - "promote_priority_when_team_full": 750 + "promote_priority_when_team_full": 750, + "recruit_priority_offset": [ + [ + 0, + 600 + ], + [ + 2, + -400 + ] + ] }, { "name": "玛恩纳", @@ -65,7 +117,17 @@ "alternate_skill": 2, "recruit_priority": 750, "promote_priority": 700, - "promote_priority_when_team_full": 750 + "promote_priority_when_team_full": 750, + "recruit_priority_offset": [ + [ + 0, + -750 + ], + [ + 4, + 100 + ] + ] }, { "name": "煌", @@ -88,14 +150,30 @@ "alternate_skill": 1, "recruit_priority": 750, "promote_priority": 800, - "promote_priority_when_team_full": 800 + "promote_priority_when_team_full": 800, + "recruit_priority_offset": [ + [ + 3, + 100 + ] + ] }, { "name": "艾丽妮", "skill": 3, "alternate_skill": 1, "recruit_priority": 750, - "promote_priority": 750 + "promote_priority": 750, + "recruit_priority_offset": [ + [ + 0, + -750 + ], + [ + 2, + 200 + ] + ] }, { "name": "陈", @@ -321,14 +399,26 @@ "skill": 2, "recruit_priority": 550, "promote_priority": 550, - "promote_priority_when_team_full": 750 + "promote_priority_when_team_full": 750, + "recruit_priority_offset": [ + [ + 2, + -550 + ] + ] }, { "name": "蓝毒", "skill": 1, "recruit_priority": 550, "promote_priority": 550, - "promote_priority_when_team_full": 750 + "promote_priority_when_team_full": 750, + "recruit_priority_offset": [ + [ + 2, + -550 + ] + ] }, { "name": "梅", diff --git a/src/MeoAssistant/Resource/RoguelikeCopilotConfiger.cpp b/src/MeoAssistant/Resource/RoguelikeCopilotConfiger.cpp index 18579e6f81..d25c2d1fd4 100644 --- a/src/MeoAssistant/Resource/RoguelikeCopilotConfiger.cpp +++ b/src/MeoAssistant/Resource/RoguelikeCopilotConfiger.cpp @@ -81,34 +81,7 @@ bool asst::RoguelikeCopilotConfiger::parse(const json::value& json) BattleRole::Warrior, BattleRole::Pioneer, BattleRole::Medic, BattleRole::Tank, BattleRole::Sniper, BattleRole::Caster, BattleRole::Support, BattleRole::Special, BattleRole::Drone, }; - static const std::unordered_map NameToRole = { - { "warrior", BattleRole::Warrior }, { "WARRIOR", BattleRole::Warrior }, - { "Warrior", BattleRole::Warrior }, { "近卫", BattleRole::Warrior }, - - { "pioneer", BattleRole::Pioneer }, { "PIONEER", BattleRole::Pioneer }, - { "Pioneer", BattleRole::Pioneer }, { "先锋", BattleRole::Pioneer }, - - { "medic", BattleRole::Medic }, { "MEDIC", BattleRole::Medic }, - { "Medic", BattleRole::Medic }, { "医疗", BattleRole::Medic }, - - { "tank", BattleRole::Tank }, { "TANK", BattleRole::Tank }, - { "Tank", BattleRole::Tank }, { "重装", BattleRole::Tank }, - - { "sniper", BattleRole::Sniper }, { "SNIPER", BattleRole::Sniper }, - { "Sniper", BattleRole::Sniper }, { "狙击", BattleRole::Sniper }, - - { "caster", BattleRole::Caster }, { "CASTER", BattleRole::Caster }, - { "Caster", BattleRole::Caster }, { "术师", BattleRole::Caster }, - - { "support", BattleRole::Support }, { "SUPPORT", BattleRole::Support }, - { "Support", BattleRole::Support }, { "辅助", BattleRole::Support }, - - { "special", BattleRole::Special }, { "SPECIAL", BattleRole::Special }, - { "Special", BattleRole::Special }, { "特种", BattleRole::Special }, - - { "drone", BattleRole::Drone }, { "DRONE", BattleRole::Drone }, - { "Drone", BattleRole::Drone }, { "无人机", BattleRole::Drone }, - }; + auto to_lower = [](char c) -> char { return static_cast(std::tolower(c)); }; if (auto opt = stage_info.find("role_order")) { const auto& raw_roles = opt.value(); @@ -126,19 +99,19 @@ bool asst::RoguelikeCopilotConfiger::parse(const json::value& json) return std::move(name); }); for (const std::string& role_name : roles) { - auto iter = NameToRole.find(role_name); - if (iter == NameToRole.end()) [[unlikely]] { + const auto role = get_role_type(role_name); + if (role == BattleRole::Unknown) [[unlikely]] { Log.error("Unknown BattleRole:", role_name); is_legal = false; break; } - if (specified_role.contains(iter->second)) [[unlikely]] { + if (specified_role.contains(role)) [[unlikely]] { Log.error("Duplicated BattleRole:", role_name); is_legal = false; break; } - specified_role.emplace(iter->second); - role_order.emplace_back(iter->second); + specified_role.emplace(role); + role_order.emplace_back(role); } if (is_legal) [[likely]] { ranges::copy(RoleOrder | filter([&](BattleRole role) { return !specified_role.contains(role); }), @@ -173,16 +146,16 @@ bool asst::RoguelikeCopilotConfiger::parse(const json::value& json) Log.error("Unknown direction"); return false; } - std::unordered_set role; + std::unordered_set fd_role; for (auto& role_name : point["role"].as_array()) { - auto iter = NameToRole.find(role_name.as_string()); - if (iter == NameToRole.end()) [[unlikely]] { + const auto role = get_role_type(role_name.as_string()); + if (role == BattleRole::Unknown) [[unlikely]] { Log.error("Unknown role name:", role_name); return false; } - role.emplace(iter->second); + fd_role.emplace(role); } - fd_dir.role = std::move(role); + fd_dir.role = std::move(fd_role); data.force_deploy_direction.emplace(location, fd_dir); } } diff --git a/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.cpp b/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.cpp index ec76e26dca..c1621ccc95 100644 --- a/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.cpp +++ b/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.cpp @@ -37,6 +37,12 @@ bool asst::RoguelikeRecruitConfiger::parse(const json::value& json) info.alternate_skill = oper_info.get("alternate_skill", 0); info.skill_usage = static_cast(oper_info.get("skill_usage", 1)); info.alternate_skill_usage = static_cast(oper_info.get("alternate_skill_usage", 1)); + if (auto opt = oper_info.find("recruit_priority_offset")) { + for (const auto& offset : opt.value()) { + std::pair offset_pair = std::make_pair(offset[0].as_integer(), offset[1].as_integer()); + info.recruit_priority_offset.emplace_back(offset_pair); + } + } m_all_opers.emplace(name, std::move(info)); m_ordered_all_opers_name.emplace_back(name); diff --git a/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.h b/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.h index 3d026e1718..ea0c9bbaa6 100644 --- a/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.h +++ b/src/MeoAssistant/Resource/RoguelikeRecruitConfiger.h @@ -19,6 +19,7 @@ namespace asst int promote_priority = 0; // 晋升优先级 (0-1000) int recruit_priority_when_team_full = 0; // 队伍满时的招募优先级 (0-1000) int promote_priority_when_team_full = 0; // 队伍满时的晋升优先级 (0-1000) + std::vector> recruit_priority_offset; bool is_alternate = false; // 是否后备干员 (允许重复招募、划到后备干员时不再往右划动) int skill = 0; int alternate_skill = 0; diff --git a/src/MeoAssistant/RuntimeStatus.h b/src/MeoAssistant/RuntimeStatus.h index 364b64900f..700f5545c1 100644 --- a/src/MeoAssistant/RuntimeStatus.h +++ b/src/MeoAssistant/RuntimeStatus.h @@ -45,6 +45,7 @@ namespace asst static inline const std::string RoguelikeTraderNoLongerBuy = "RoguelikeNoLongerBuy"; static inline const std::string RoguelikeSkillUsagePrefix = "RoguelikeSkillUsage-"; static inline const std::string RoguelikeTeamFullWithoutRookie = "RoguelikeTeamFullWithoutRookie"; + static inline const std::string RoguelikeTeamRoles = "RoguelikeTeamRoles"; static inline const std::string RoguelikeTheme = "RoguelikeTheme"; private: diff --git a/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.cpp b/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.cpp index 03e9299f65..d481b7f3ec 100644 --- a/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.cpp +++ b/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.cpp @@ -4,6 +4,7 @@ #include "Controller.h" #include "ImageAnalyzer/RoguelikeRecruitImageAnalyzer.h" #include "Resource/RoguelikeRecruitConfiger.h" +#include "Resource/BattleDataConfiger.h" #include "RuntimeStatus.h" #include "TaskData.h" #include "Utils/Logger.hpp" @@ -33,6 +34,11 @@ bool asst::RoguelikeRecruitTaskPlugin::verify(AsstMsg msg, const json::value& de } } +std::string asst::RoguelikeRecruitTaskPlugin::get_oper_role(const std::string& name) +{ + return std::to_string(BattleData.get_role(name)); +} + bool asst::RoguelikeRecruitTaskPlugin::_run() { LogTraceFunction; @@ -56,6 +62,9 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() m_status->get_str(RuntimeStatus::RoguelikeCharOverview).value_or(json::value().to_string()); json::value json_chars_info = json::parse(str_chars_info).value_or(json::value()); const auto& chars_map = json_chars_info.as_object(); + std::string teamroles_str = + m_status->get_str(RuntimeStatus::RoguelikeTeamRoles).value_or(json::value().to_string()); + json::value teamroles = json::parse(teamroles_str).value_or(json::value()); // 候选干员 std::vector recruit_list; @@ -153,6 +162,13 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() Log.trace(__FUNCTION__, "| Ignored low level oper:", oper_info.name, oper_info.elite, oper_info.level); } + int role_num = teamroles.get(get_oper_role(oper_info.name), 0); + for (const auto& offset_pair : ranges::reverse_view(recruit_info.recruit_priority_offset)) { + if (role_num >= offset_pair.first) { + priority += offset_pair.second; + break; + } + } } // 优先级为0,可能练度不够被忽略 @@ -246,7 +262,7 @@ bool asst::RoguelikeRecruitTaskPlugin::_run() return false; } - auto& char_name = selected_oper->name; + std::string char_name = selected_oper->name; Log.trace(__FUNCTION__, "| Top priority oper:", char_name, selected_oper->priority, "page", selected_oper->page_index, "/", i); @@ -355,6 +371,18 @@ void asst::RoguelikeRecruitTaskPlugin::select_oper(const BattleRecruitOperInfo& { "level", oper.level }, }; m_status->set_str(RuntimeStatus::RoguelikeCharOverview, overview.to_string()); + + auto& recruit_info = RoguelikeRecruit.get_oper_info(oper.name); + if (recruit_info.name.empty() || recruit_info.is_alternate) { + return; + } + std::string teamroles_str = + m_status->get_str(RuntimeStatus::RoguelikeTeamRoles).value_or(json::value().to_string()); + json::value teamroles = json::parse(teamroles_str).value_or(json::value()); + std::string role_name = get_oper_role(oper.name); + int role_num = teamroles.get(role_name, 0) + 1; + teamroles[std::move(role_name)] = role_num; + m_status->set_str(RuntimeStatus::RoguelikeTeamRoles, teamroles.to_string()); } void asst::RoguelikeRecruitTaskPlugin::swipe_to_the_left_of_operlist(int loop_times) diff --git a/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.h b/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.h index cefcc232ee..b3d4621c32 100644 --- a/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.h +++ b/src/MeoAssistant/Task/Plugin/RoguelikeRecruitTaskPlugin.h @@ -30,6 +30,7 @@ namespace asst private: bool check_core_char(); + std::string get_oper_role(const std::string& name); // 招募指定干员 // // 输入参数: diff --git a/src/MeoAssistant/Task/Plugin/RoguelikeResetTaskPlugin.cpp b/src/MeoAssistant/Task/Plugin/RoguelikeResetTaskPlugin.cpp index 9a43598c05..36df240cb3 100644 --- a/src/MeoAssistant/Task/Plugin/RoguelikeResetTaskPlugin.cpp +++ b/src/MeoAssistant/Task/Plugin/RoguelikeResetTaskPlugin.cpp @@ -20,7 +20,7 @@ bool asst::RoguelikeResetTaskPlugin::verify(AsstMsg msg, const json::value& deta if (task_view.starts_with(roguelike_name)) { task_view.remove_prefix(roguelike_name.length()); } - if (task_view == "Roguelike@Start") { + if (task_view == "Roguelike@StartExplore") { return true; } else { diff --git a/src/MeoAssistant/Utils/AsstBattleDef.h b/src/MeoAssistant/Utils/AsstBattleDef.h index 52ac80fe14..c1dd176e0e 100644 --- a/src/MeoAssistant/Utils/AsstBattleDef.h +++ b/src/MeoAssistant/Utils/AsstBattleDef.h @@ -95,6 +95,64 @@ namespace asst Drone }; + inline BattleRole get_role_type(const std::string& role_name) + { + static const std::unordered_map NameToRole = { + { "warrior", BattleRole::Warrior }, { "WARRIOR", BattleRole::Warrior }, + { "Warrior", BattleRole::Warrior }, { "近卫", BattleRole::Warrior }, + + { "pioneer", BattleRole::Pioneer }, { "PIONEER", BattleRole::Pioneer }, + { "Pioneer", BattleRole::Pioneer }, { "先锋", BattleRole::Pioneer }, + + { "medic", BattleRole::Medic }, { "MEDIC", BattleRole::Medic }, + { "Medic", BattleRole::Medic }, { "医疗", BattleRole::Medic }, + + { "tank", BattleRole::Tank }, { "TANK", BattleRole::Tank }, + { "Tank", BattleRole::Tank }, { "重装", BattleRole::Tank }, + + { "sniper", BattleRole::Sniper }, { "SNIPER", BattleRole::Sniper }, + { "Sniper", BattleRole::Sniper }, { "狙击", BattleRole::Sniper }, + + { "caster", BattleRole::Caster }, { "CASTER", BattleRole::Caster }, + { "Caster", BattleRole::Caster }, { "术师", BattleRole::Caster }, + + { "support", BattleRole::Support }, { "SUPPORT", BattleRole::Support }, + { "Support", BattleRole::Support }, { "辅助", BattleRole::Support }, + + { "special", BattleRole::Special }, { "SPECIAL", BattleRole::Special }, + { "Special", BattleRole::Special }, { "特种", BattleRole::Special }, + + { "drone", BattleRole::Drone }, { "DRONE", BattleRole::Drone }, + { "Drone", BattleRole::Drone }, { "无人机", BattleRole::Drone }, + }; + if (auto iter = NameToRole.find(role_name); iter != NameToRole.end()) { + return iter->second; + } + return BattleRole::Unknown; + } +} + +namespace std +{ + inline std::string to_string(const asst::BattleRole& role) + { + static const std::unordered_map RoleToName = { + { asst::BattleRole::Warrior, "Warrior" }, + { asst::BattleRole::Pioneer, "Pioneer" }, + { asst::BattleRole::Medic, "Medic" }, + { asst::BattleRole::Tank, "Tank" }, + { asst::BattleRole::Sniper, "Sniper" }, + { asst::BattleRole::Caster, "Caster" }, + { asst::BattleRole::Support, "Support" }, + { asst::BattleRole::Special, "Special" }, + { asst::BattleRole::Drone, "Drone" }, + { asst::BattleRole::Unknown, "Unknown" } + }; + return RoleToName.at(role); + } +} + +namespace asst { struct BattleRealTimeOper { int cost = 0;