feat: 支持识别并选择临时招募干员

This commit is contained in:
DuKong
2023-04-22 17:19:47 +08:00
parent 5898dfdb9d
commit 0804eed360
9 changed files with 330 additions and 77 deletions

View File

@@ -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": [ "单奶", "群奶" ],

View File

@@ -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": "“打字机”"
}
]
}

View File

@@ -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
}
}
}
}

View File

@@ -7248,6 +7248,16 @@
"Roguelike@ChooseOper"
]
},
"Roguelike@TempRecruitFlag": {
"action": "DoNothing",
"roi": [
587,
76,
100,
20
],
"templThreshold": 0.5
},
"Roguelike@ClickToDrops": {
"algorithm": "JustReturn",
"action": "ClickRect",

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -6,15 +6,18 @@
#include <meojson/json.hpp>
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<battle::SkillUsage>(oper_info.get("skill_usage", 1));
info.alternate_skill_usage = static_cast<battle::SkillUsage>(oper_info.get("alternate_skill_usage", 1));

View File

@@ -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<RecruitPriorityOffset> 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<std::pair<int, int>> get_role_info(const std::string& theme,
const battle::Role& role) const noexcept; // [deprecated]
const std::vector<std::string> get_group_info(const std::string& theme) const noexcept;

View File

@@ -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");

View File

@@ -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);