mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-06 21:00:28 +08:00
@@ -11,7 +11,6 @@
|
||||
#include "Utils/ImageIo.hpp"
|
||||
#include "Utils/Logger.hpp"
|
||||
#include "Vision/MultiMatcher.h"
|
||||
#include "Vision/Battle/BattleRecruitSupportAnalyzer.h"
|
||||
|
||||
void asst::BattleFormationTask::append_additional_formation(AdditionalFormation formation)
|
||||
{
|
||||
@@ -23,6 +22,11 @@ void asst::BattleFormationTask::set_support_unit_name(std::string name)
|
||||
m_support_unit_name = std::move(name);
|
||||
}
|
||||
|
||||
void asst::BattleFormationTask::set_add_user_additional(bool add_user_additional)
|
||||
{
|
||||
m_add_user_additional = add_user_additional;
|
||||
}
|
||||
|
||||
void asst::BattleFormationTask::set_user_additional(std::vector<std::pair<std::string, int>> user_additional)
|
||||
{
|
||||
m_user_additional = std::move(user_additional);
|
||||
@@ -38,7 +42,7 @@ void asst::BattleFormationTask::set_select_formation(int index)
|
||||
m_select_formation_index = index;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::unordered_map<std::string, std::string>> asst::BattleFormationTask::get_opers_in_formation() const
|
||||
std::shared_ptr<std::unordered_map<std::string, std::string>>asst::BattleFormationTask::get_opers_in_formation() const
|
||||
{
|
||||
return m_opers_in_formation;
|
||||
}
|
||||
@@ -68,24 +72,18 @@ bool asst::BattleFormationTask::_run()
|
||||
for (auto& [role, oper_groups] : m_formation) {
|
||||
add_formation(role, oper_groups, missing_operators);
|
||||
}
|
||||
|
||||
|
||||
if (!missing_operators.empty()) {
|
||||
bool support = false;
|
||||
if (missing_operators.size() == 1) {
|
||||
// 记得加上 SupportUnitUsage 的壳
|
||||
support = select_support_operator(
|
||||
missing_operators.front().first,
|
||||
missing_operators.front().second.front().skill);
|
||||
// TODO: 自动借助战?
|
||||
}
|
||||
if (support) return true;
|
||||
|
||||
report_missing_operators(missing_operators);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 对于有在干员组中存在的自定干员,无法提前得知是否成功编入,故不提前加入编队
|
||||
if (!m_user_additional.empty()) {
|
||||
if (m_add_user_additional) {
|
||||
auto limit = 12 - m_size_of_operators_in_formation;
|
||||
for (const auto& [name, skill] : m_user_additional) {
|
||||
if (m_opers_in_formation->contains(name)) {
|
||||
@@ -98,11 +96,9 @@ bool asst::BattleFormationTask::_run()
|
||||
oper.name = name;
|
||||
oper.skill = skill;
|
||||
std::vector<asst::battle::OperUsage> usage { std::move(oper) };
|
||||
m_user_formation[BattleData.get_role(name)].emplace_back(name, std::move(usage));
|
||||
}
|
||||
for (auto& [role, oper_groups] : m_user_formation) {
|
||||
add_formation(role, oper_groups, missing_operators);
|
||||
m_user_formation.emplace_back(name, std::move(usage));
|
||||
}
|
||||
add_formation(battle::Role::Unknown, m_user_formation, missing_operators);
|
||||
}
|
||||
|
||||
add_additional();
|
||||
@@ -121,93 +117,6 @@ bool asst::BattleFormationTask::_run()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asst::BattleFormationTask::select_support_operator(const std::string name, int skill)
|
||||
{
|
||||
ProcessTask(*this, { "SelectSupportEnter" }).run();
|
||||
ProcessTask(*this, { "SupportOperRole" + enum_to_string(BattleData.get_role(name), true) }).run();
|
||||
|
||||
// 识别所有干员,应该最多两页
|
||||
const int MaxPageCnt = 2;
|
||||
const int max_refresh = 10;
|
||||
|
||||
std::vector<battle::roguelike::RecruitSupportCharInfo> satisfied_chars;
|
||||
for (int retry = 0; retry <= max_refresh; ++retry) {
|
||||
if (need_exit()) return false;
|
||||
for (int page = 0; page < MaxPageCnt; ++page) {
|
||||
auto screen_char = ctrler()->get_image();
|
||||
BattleRecruitSupportAnalyzer analyzer_char(screen_char);
|
||||
analyzer_char.set_mode(battle::roguelike::SupportAnalyzeMode::AnalyzeChars);
|
||||
analyzer_char.set_required({ name });
|
||||
if (analyzer_char.analyze()) {
|
||||
auto& chars_page = analyzer_char.get_result_char();
|
||||
|
||||
bool use_nonfriend_support = true;
|
||||
auto check_satisfy = [&use_nonfriend_support](const battle::roguelike::RecruitSupportCharInfo& chara) {
|
||||
return chara.is_friend || use_nonfriend_support;
|
||||
};
|
||||
std::copy_if(
|
||||
chars_page.begin(),
|
||||
chars_page.end(),
|
||||
std::inserter(satisfied_chars, std::begin(satisfied_chars)),
|
||||
check_satisfy);
|
||||
|
||||
if (satisfied_chars.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (page != MaxPageCnt - 1) {
|
||||
ProcessTask(*this, { "RoguelikeSupportSwipeRight" }).run();
|
||||
}
|
||||
}
|
||||
if (satisfied_chars.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 刷新助战
|
||||
if (retry >= max_refresh) {
|
||||
break;
|
||||
}
|
||||
auto screen_refresh = ctrler()->get_image();
|
||||
BattleRecruitSupportAnalyzer analyzer_refresh(screen_refresh);
|
||||
analyzer_refresh.set_mode(battle::roguelike::SupportAnalyzeMode::RefreshSupportBtn);
|
||||
if (!analyzer_refresh.analyze()) {
|
||||
click_return_button();
|
||||
return false;
|
||||
}
|
||||
auto& refresh_info = analyzer_refresh.get_result_refresh();
|
||||
if (refresh_info.in_cooldown) {
|
||||
sleep(refresh_info.remain_secs * 1000);
|
||||
}
|
||||
ctrler()->click(refresh_info.rect);
|
||||
sleep(Task.get("RoguelikeRefreshSupportBtnOcr")->post_delay);
|
||||
ProcessTask(*this, { "RoguelikeSupportSwipeLeft" }).run();
|
||||
}
|
||||
if (satisfied_chars.empty()) {
|
||||
// 找不到需要的助战干员,返回正常招募逻辑
|
||||
Log.info(__FUNCTION__, "| can't find support char `", name, "`");
|
||||
click_return_button();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 点击干员并记录信息
|
||||
auto& satisfied_char = satisfied_chars.front();
|
||||
|
||||
// 选择干员
|
||||
const battle::roguelike::Recruitment& oper = satisfied_char.oper_info;
|
||||
|
||||
Log.info(__FUNCTION__, "| Choose support oper:", oper.name, "( elite", oper.elite, "level", oper.level, ")");
|
||||
|
||||
ctrler()->click(oper.rect);
|
||||
|
||||
// 选择技能
|
||||
ProcessTask(*this, { "SelectSupportOperSkill" + std::to_string(skill) }).run();
|
||||
|
||||
// 确认选择
|
||||
ProcessTask(*this, { "RecruitSupportConfirm" }).run();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool asst::BattleFormationTask::add_formation(battle::Role role, std::vector<OperGroup> oper_group, std::vector<OperGroup>& missing)
|
||||
{
|
||||
LogTraceFunction;
|
||||
@@ -236,7 +145,7 @@ bool asst::BattleFormationTask::add_formation(battle::Role role, std::vector<Ope
|
||||
}
|
||||
else {
|
||||
if (overall_swipe_times == m_missing_retry_times) {
|
||||
missing.insert(missing.end(), oper_group.begin(), oper_group.end());
|
||||
missing.insert(missing.end(), oper_group.begin(), oper_group.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -315,8 +224,9 @@ bool asst::BattleFormationTask::add_trust_operators()
|
||||
ProcessTask(*this, { "BattleQuickFormationFilter-Trust" }).run();
|
||||
ProcessTask(*this, { "BattleQuickFormationFilterClose" }).run();
|
||||
// 检查特关是否开启
|
||||
ProcessTask(*this, { "BattleQuickFormationFilter-PinUnactivated", "BattleQuickFormationFilter-PinActivated" })
|
||||
.run();
|
||||
ProcessTask(*this, {
|
||||
"BattleQuickFormationFilter-PinUnactivated", "BattleQuickFormationFilter-PinActivated"
|
||||
}).run();
|
||||
|
||||
// 重置职业选择,保证处于最左
|
||||
click_role_table(battle::Role::Caster);
|
||||
@@ -521,9 +431,7 @@ bool asst::BattleFormationTask::click_role_table(battle::Role role)
|
||||
tasks = { "BattleQuickFormationRole-All", "BattleQuickFormationRole-All-OCR" };
|
||||
}
|
||||
else {
|
||||
tasks = { "BattleQuickFormationRole-" + role_iter->second,
|
||||
"BattleQuickFormationRole-All",
|
||||
"BattleQuickFormationRole-All-OCR" };
|
||||
tasks = { "BattleQuickFormationRole-" + role_iter->second, "BattleQuickFormationRole-All", "BattleQuickFormationRole-All-OCR"};
|
||||
}
|
||||
return ProcessTask(*this, tasks).set_retry_times(0).run();
|
||||
}
|
||||
@@ -567,8 +475,7 @@ bool asst::BattleFormationTask::select_formation(int select_index)
|
||||
// 第二组是名字最左边和最右边的一块区域
|
||||
// 右边比左边窄,暂定为左边 10*58
|
||||
|
||||
static const std::vector<std::string> select_formation_task = { "BattleSelectFormation1",
|
||||
"BattleSelectFormation2",
|
||||
static const std::vector<std::string> select_formation_task = { "BattleSelectFormation1", "BattleSelectFormation2",
|
||||
"BattleSelectFormation3",
|
||||
"BattleSelectFormation4" };
|
||||
|
||||
|
||||
@@ -7,13 +7,7 @@
|
||||
|
||||
namespace asst
|
||||
{
|
||||
class BattleFormationTask : public AbstractTask
|
||||
{
|
||||
public:
|
||||
using AbstractTask::AbstractTask;
|
||||
virtual ~BattleFormationTask() override = default;
|
||||
|
||||
enum class Filter
|
||||
class BattleFormationTask : public AbstractTask
|
||||
{
|
||||
public:
|
||||
using AbstractTask::AbstractTask;
|
||||
@@ -70,7 +64,6 @@ public:
|
||||
bool select_formation(int select_index);
|
||||
bool select_random_support_unit();
|
||||
void report_missing_operators(std::vector<OperGroup>& groups);
|
||||
bool select_support_operator(const std::string name, int skill = 0);
|
||||
|
||||
std::vector<asst::TemplDetOCRer::Result> analyzer_opers();
|
||||
|
||||
@@ -90,69 +83,4 @@ public:
|
||||
int m_select_formation_index = 0;
|
||||
int m_missing_retry_times = 1; // 识别不到干员的重试次数
|
||||
};
|
||||
|
||||
struct AdditionalFormation
|
||||
{
|
||||
Filter filter = Filter::None;
|
||||
bool double_click_filter = true;
|
||||
battle::RoleCounts role_counts;
|
||||
};
|
||||
|
||||
void append_additional_formation(AdditionalFormation formation);
|
||||
|
||||
void set_support_unit_name(std::string name);
|
||||
// 是否追加自定干员
|
||||
void set_add_user_additional(bool add_user_additional);
|
||||
// 设置追加自定干员列表
|
||||
void set_user_additional(std::vector<std::pair<std::string, int>> user_additional);
|
||||
// 是否追加低信赖干员
|
||||
void set_add_trust(bool add_trust);
|
||||
// 设置对指定编队自动编队
|
||||
void set_select_formation(int index);
|
||||
std::shared_ptr<std::unordered_map<std::string, std::string>> get_opers_in_formation() const;
|
||||
|
||||
enum class DataResource
|
||||
{
|
||||
Copilot,
|
||||
SSSCopilot,
|
||||
};
|
||||
void set_data_resource(DataResource resource);
|
||||
|
||||
protected:
|
||||
using OperGroup = std::pair<std::string, std::vector<asst::battle::OperUsage>>;
|
||||
|
||||
virtual bool _run() override;
|
||||
bool add_formation(battle::Role role, std::vector<OperGroup> oper_group, std::vector<OperGroup>& missing);
|
||||
// 追加附加干员(按部署费用等小分类)
|
||||
bool add_additional();
|
||||
// 补充刷信赖的干员,从最小的开始
|
||||
bool add_trust_operators();
|
||||
bool enter_selection_page();
|
||||
bool select_opers_in_cur_page(std::vector<OperGroup>& groups);
|
||||
void swipe_page();
|
||||
void swipe_to_the_left(int times = 2);
|
||||
bool confirm_selection();
|
||||
bool click_role_table(battle::Role role);
|
||||
bool parse_formation();
|
||||
bool select_formation(int select_index);
|
||||
bool select_random_support_unit();
|
||||
void report_missing_operators(std::vector<OperGroup>& groups);
|
||||
|
||||
std::vector<asst::TemplDetOCRer::Result> analyzer_opers();
|
||||
|
||||
std::string m_stage_name;
|
||||
std::unordered_map<battle::Role, std::vector<OperGroup>> m_formation;
|
||||
std::unordered_map<battle::Role, std::vector<OperGroup>> m_user_formation;
|
||||
int m_size_of_operators_in_formation = 0; // 编队中干员个数
|
||||
std::shared_ptr<std::unordered_map<std::string, std::string>> m_opers_in_formation =
|
||||
std::make_shared<std::unordered_map<std::string, std::string>>(); // 编队中的干员名称-所属组名
|
||||
bool m_add_trust = false; // 是否需要追加信赖干员
|
||||
std::vector<std::pair<std::string, int>> m_user_additional; // 追加干员表,从头往后加
|
||||
std::string m_support_unit_name;
|
||||
DataResource m_data_resource = DataResource::Copilot;
|
||||
std::vector<AdditionalFormation> m_additional;
|
||||
std::string m_last_oper_name;
|
||||
int m_select_formation_index = 0;
|
||||
int m_missing_retry_times = 1; // 识别不到干员的重试次数
|
||||
};
|
||||
} // namespace asst
|
||||
|
||||
Reference in New Issue
Block a user