Files
MaaAssistantArknights/src/MaaCore/Task/BattleHelper.h
Status102 88a1e4fb68 rft: 干员数据重构, 支持跨职业重名干员 (#16084)
* rft: 干员数据重构, 支持跨职业重名干员

* fix: 查找优化

* fix: default value

* perf: 重新加载时清空数据

* fix: 默认值

* perf: 查找
2026-04-08 11:39:52 +08:00

141 lines
5.6 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.
#pragma once
#include "AbstractTask.h"
#include "Common/AsstBattleDef.h"
#include "Config/Miscellaneous/TilePack.h"
#include "InstHelper.h"
#include "MaaUtils/NoWarningCVMat.hpp"
#include "Utils/Platform.hpp"
#include "Utils/WorkingDir.hpp"
#include "Vision/BestMatcher.h"
#include <concepts>
#include <filesystem>
#include <map>
namespace asst
{
template <typename T>
concept OperAvatarPair = requires {
typename T::first_type;
typename T::second_type;
requires std::same_as<std::string, std::remove_cvref_t<typename T::first_type>>;
requires std::same_as<cv::Mat, std::remove_cvref_t<typename T::second_type>>;
};
class BattleHelper
{
public:
~BattleHelper() = default;
protected:
BattleHelper(Assistant* inst);
virtual AbstractTask& this_task() = 0;
virtual bool set_stage_name(const std::string& name);
virtual void clear();
virtual const std::string oper_name_ocr_task_name() const noexcept { return "BattleOperName"; }
virtual bool do_strategic_action(const cv::Mat& reusable = cv::Mat());
bool calc_tiles_info(const std::string& stage_name, double shift_x = 0, double shift_y = 0);
bool pause();
bool speed_up();
bool abandon();
bool update_deployment(bool init = false, const cv::Mat& reusable = cv::Mat(), bool need_oper_cost = false);
// 更新部署区的干员仅当存在未识别干员且不处于冷却中return false
bool update_deployment_(
std::vector<battle::DeploymentOper>& cur_opers,
const std::vector<battle::DeploymentOper>& old_deployment_opers,
bool stop_on_unknown);
bool update_kills(const cv::Mat& image, const cv::Mat& image_prev = cv::Mat());
bool update_cost(const cv::Mat& image, const cv::Mat& image_prev = cv::Mat());
cv::Mat get_top_view(const cv::Mat& cam_img, bool side = true, bool has_multi_stages = false);
bool deploy_oper(const std::string& name, const Point& loc, battle::DeployDirection direction);
bool retreat_oper(const std::string& name);
bool retreat_oper(const Point& loc, bool manually = true);
bool is_skill_ready(const Point& loc, const cv::Mat& reusable = cv::Mat());
bool is_skill_ready(const std::string& name, const cv::Mat& reusable = cv::Mat());
bool use_skill(const std::string& name, bool keep_waiting = true);
bool use_skill(const Point& loc, bool keep_waiting = true);
bool check_pause_button(const cv::Mat& reusable = cv::Mat());
bool check_skip_plot_button(const cv::Mat& reusable = cv::Mat());
// 检查是否有战斗中带头像的对话框
bool check_avatar_dialog(const cv::Mat& reusable = cv::Mat());
// 检查是否处于二倍速
bool check_in_speedup(const cv::Mat& reusable = cv::Mat());
virtual bool check_in_battle(const cv::Mat& reusable = cv::Mat(), bool weak = true);
virtual bool wait_until_start(bool weak = true);
bool wait_until_end(bool weak = true);
bool use_all_ready_skill(const cv::Mat& reusable = cv::Mat());
bool check_and_use_skill(const std::string& name, bool& has_error, const cv::Mat& reusable = cv::Mat());
bool check_and_use_skill(const Point& loc, bool& has_error, const cv::Mat& reusable = cv::Mat());
void save_map(const cv::Mat& image);
bool click_oper_on_deployment(const std::string& name);
bool click_oper_on_deployment(const Rect& rect);
bool click_oper_on_battlefield(const std::string& name);
bool click_oper_on_battlefield(const Point& loc);
bool click_retreat(); // 这个是不带识别的,直接点
bool click_skill(bool keep_waiting = true); // 这个是带识别的,转好了才点
bool cancel_oper_selection();
// 修正终点超出范围的滑动,纠正时是否需要顺时针旋转
void fix_swipe_out_of_limit(
Point& p1,
Point& p2,
int width,
int height,
int max_distance = INT_MAX,
double radian = 0);
bool move_camera(const std::pair<double, double>& delta);
std::string analyze_detail_page_oper_name(const cv::Mat& image, battle::Role role);
std::optional<Rect> get_oper_rect_on_deployment(const std::string& name) const;
int elapsed_time();
// 注册已部署干员及位置
void register_deployed_oper(const std::string& name, const Point& loc);
// 从场上干员和已占用格子中移除冷却中的干员
void remove_cooling_from_battlefield(const battle::DeploymentOper& oper);
std::string m_stage_name;
Map::Level m_map_data;
std::unordered_map<Point, TilePack::TileInfo> m_side_tile_info; // 子弹时间的坐标映射
std::unordered_map<Point, TilePack::TileInfo> m_normal_tile_info; // 正常的坐标映射
Point m_skill_button_pos;
Point m_retreat_button_pos;
bool m_has_multi_stages = false;
std::unordered_map<std::string, battle::SkillUsage> m_skill_usage;
std::unordered_map<std::string, int> m_skill_times;
std::unordered_map<std::string, int> m_skill_error_count;
std::unordered_map<std::string, std::chrono::steady_clock::time_point> m_last_use_skill_time;
int m_camera_count = 0;
bool m_in_speedup = false; // 是否处于2倍速
std::pair<double, double> m_camera_shift = { 0., 0. };
/* 实时更新的数据 */
bool m_in_battle = false;
int m_kills = 0;
int m_total_kills = 0;
int m_cost = 0;
bool m_stopwatch_enabled = false;
std::chrono::steady_clock::time_point m_stopwatch_start_time;
std::vector<battle::DeploymentOper> m_cur_deployment_opers;
std::map<std::string, Point> m_battlefield_opers;
std::map<Point, std::string> m_used_tiles;
private:
InstHelper m_inst_helper;
};
} // namespace asst