Files
MaaAssistantArknights/src/MeoAssistant/BattleFormationTask.cpp
2022-09-04 01:30:53 +08:00

184 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "BattleFormationTask.h"
#include "AsstRanges.hpp"
#include "BattleDataConfiger.h"
#include "Controller.h"
#include "CopilotConfiger.h"
#include "Logger.hpp"
#include "OcrWithFlagTemplImageAnalyzer.h"
#include "ProcessTask.h"
#include "TaskData.h"
void asst::BattleFormationTask::set_stage_name(std::string name)
{
m_stage_name = std::move(name);
}
bool asst::BattleFormationTask::_run()
{
LogTraceFunction;
if (!parse_formation()) {
return false;
}
if (!enter_selection_page()) {
return false;
}
for (auto& [role, oper_groups] : m_formation) {
click_role_table(role);
// TODO: 需要加一个滑到头了的检测
while (!need_exit()) {
select_opers_in_cur_page(oper_groups);
if (oper_groups.empty()) {
break;
}
swipe_page();
}
}
confirm_selection();
return true;
}
bool asst::BattleFormationTask::enter_selection_page()
{
return ProcessTask(*this, { "BattleQuickFormation" }).run();
}
bool asst::BattleFormationTask::select_opers_in_cur_page(std::vector<OperGroup>& groups)
{
auto formation_task_ptr = Task.get("BattleQuickFormationOCR");
auto image = m_ctrler->get_image();
auto& ocr_replace = Task.get<OcrTaskInfo>("CharsNameOcrReplace")->replace_map;
OcrWithFlagTemplImageAnalyzer name_analyzer(image);
name_analyzer.set_task_info("BattleQuickFormation-OperNameFlag", "BattleQuickFormationOCR");
name_analyzer.set_replace(ocr_replace);
name_analyzer.analyze();
OcrWithFlagTemplImageAnalyzer special_focus_analyzer(image);
special_focus_analyzer.set_task_info("BattleQuickFormation-OperNameFlag-SpecialFocus", "BattleQuickFormationOCR");
special_focus_analyzer.set_replace(ocr_replace);
special_focus_analyzer.analyze();
auto opers_result = name_analyzer.get_result();
const auto& special_focus_res = special_focus_analyzer.get_result();
opers_result.insert(opers_result.end(), special_focus_res.cbegin(), special_focus_res.cend());
if (opers_result.empty()) {
return false;
}
// 按位置排个序
ranges::sort(opers_result, [](const TextRect& lhs, const TextRect& rhs) -> bool {
if (std::abs(lhs.rect.y - rhs.rect.y) < 5) { // y差距较小则理解为是同一排的按x排序
return lhs.rect.x < rhs.rect.x;
}
else {
return lhs.rect.y < rhs.rect.y;
}
});
static const std::array<Rect, 3> SkillRectArray = {
Task.get("BattleQuickFormationSkill1")->specific_rect,
Task.get("BattleQuickFormationSkill2")->specific_rect,
Task.get("BattleQuickFormationSkill3")->specific_rect,
};
int skill = 1;
for (const auto& res : opers_result) {
const std::string& name = res.text;
auto iter = groups.begin();
bool found = false;
for (; iter != groups.end(); ++iter) {
for (const auto& oper : *iter) {
if (oper.name == name) {
found = true;
skill = oper.skill;
break;
}
}
if (found) {
break;
}
}
if (iter == groups.end()) {
continue;
}
m_ctrler->click(res.rect);
sleep(formation_task_ptr->rear_delay);
if (1 <= skill && skill <= 3) {
m_ctrler->click(SkillRectArray.at(skill - 1ULL));
}
groups.erase(iter);
json::value info = basic_info_with_what("BattleFormationSelected");
auto& details = info["details"];
details["selected"] = name;
callback(AsstMsg::SubTaskExtraInfo, info);
}
return true;
}
void asst::BattleFormationTask::swipe_page()
{
static Rect begin_rect = Task.get("InfrastOperListSwipeBegin")->specific_rect;
static Rect end_rect = Task.get("InfrastOperListSwipeEnd")->specific_rect;
static int duration = Task.get("InfrastOperListSwipeBegin")->pre_delay;
m_ctrler->swipe(begin_rect, end_rect, duration, true, Task.get("InfrastOperListSwipeBegin")->rear_delay, true);
}
bool asst::BattleFormationTask::confirm_selection()
{
return ProcessTask(*this, { "BattleQuickFormationConfirm" }).run();
}
bool asst::BattleFormationTask::click_role_table(BattleRole role)
{
static const std::unordered_map<BattleRole, std::string> RoleNameType = {
{ BattleRole::Caster, "Caster" }, { BattleRole::Medic, "Medic" }, { BattleRole::Pioneer, "Pioneer" },
{ BattleRole::Sniper, "Sniper" }, { BattleRole::Special, "Special" }, { BattleRole::Support, "Support" },
{ BattleRole::Tank, "Tank" }, { BattleRole::Warrior, "Warrior" },
};
auto role_iter = RoleNameType.find(role);
if (role_iter == RoleNameType.cend()) {
return ProcessTask(*this, { "BattleQuickFormationRole-All" }).set_retry_times(0).run();
}
else {
return ProcessTask(*this, { "BattleQuickFormationRole-" + role_iter->second }).set_retry_times(0).run();
}
}
bool asst::BattleFormationTask::parse_formation()
{
if (!Copilot.contains_actions(m_stage_name)) {
Log.error("Unknown stage name", m_stage_name);
return false;
}
const auto& group = Copilot.get_actions(m_stage_name).groups;
json::value info = basic_info_with_what("BattleFormation");
auto& details = info["details"];
auto& formation = details["formation"];
for (const auto& [name, opers_vec] : group) {
if (opers_vec.empty()) {
continue;
}
formation.array_emplace(name);
BattleRole role = BattleData.get_role(opers_vec.front().name);
m_formation[role].emplace_back(opers_vec);
}
callback(AsstMsg::SubTaskExtraInfo, info);
return true;
}