feat: 合并 处于战斗中 检测, 增加倍速记忆, 支持战斗中 不带跳过按钮的 带头像对话教程 (#15706)

* rft: 合并 处于战斗中 检测, 增加倍速记忆

* feat: 支持战斗中 不带跳过按钮的 带头像对话教程

* perf: 增加重试次数上限

* perf: 2倍速检查一致化
This commit is contained in:
Status102
2026-03-07 00:30:36 +08:00
committed by GitHub
parent 7fcaf1215a
commit f6c39c3a8f
6 changed files with 56 additions and 30 deletions

View File

@@ -3577,6 +3577,13 @@
"template": "SkipThePreBattlePlotConfirm.png",
"next": ["EndOfPlot"]
},
"BattleAvatarDialog": {
"doc": "战斗中带头像对话框, 类似于 SkipThePreBattlePlot(可见于画中人关卡) 的, 但是缺少 跳过 按钮",
"action": "ClickSelf",
"roi": [70, 30, 120, 30],
"next": ["BattleAvatarDialog", "Stop"],
"rectMove": [125, 20, 200, 60]
},
"EndOfPlot": {
"roi": [520, 0, 243, 206],
"action": "ClickRect",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -618,7 +618,20 @@ bool asst::BattleHelper::check_skip_plot_button(const cv::Mat& reusable)
return ret;
}
bool asst::BattleHelper::check_in_speed_up(const cv::Mat& reusable)
bool asst::BattleHelper::check_avatar_dialog(const cv::Mat& reusable)
{
cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable;
Matcher battle_plot_analyzer(image);
battle_plot_analyzer.set_task_info("BattleAvatarDialog");
bool ret = battle_plot_analyzer.analyze().has_value();
if (ret) {
ProcessTask(this_task(), { "BattleAvatarDialog" }).run();
}
return ret;
}
bool asst::BattleHelper::check_in_speedup(const cv::Mat& reusable)
{
cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable;
Matcher analyzer(image);
@@ -631,7 +644,27 @@ bool asst::BattleHelper::check_in_battle(const cv::Mat& reusable, bool weak)
cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable;
if (weak) {
BattlefieldMatcher analyzer(image);
m_in_battle = analyzer.analyze().has_value();
auto result = analyzer.analyze();
m_in_battle = result.has_value();
if (m_in_battle && !result->pause_button) {
if (check_skip_plot_button(image)) {
if (m_in_speedup && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
}
}
else if (check_avatar_dialog(image)) {
if (m_in_speedup && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
m_inst_helper.sleep(Config.get_options().task_delay);
int times = 0;
while (times < 20 && !m_inst_helper.need_exit() && !check_in_speedup()) {
speed_up(); // 跳过剧情会退出2倍速
m_inst_helper.sleep(Config.get_options().task_delay);
times++;
}
}
}
}
}
else {
check_skip_plot_button(image);

View File

@@ -67,7 +67,10 @@ protected:
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_in_speed_up(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);
@@ -115,6 +118,7 @@ protected:
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. };
/* 实时更新的数据 */

View File

@@ -238,6 +238,9 @@ bool asst::BattleProcessTask::do_action(const battle::copilot::Action& action, s
case ActionType::SwitchSpeed:
ret = speed_up();
if (ret) {
m_in_speedup = !m_in_speedup;
}
break;
case ActionType::BulletTime:
@@ -480,31 +483,12 @@ void asst::BattleProcessTask::sleep_and_do_strategy(unsigned millisecond)
const auto start = std::chrono::steady_clock::now();
const auto delay = millisecond * 1ms;
while (!need_exit() && std::chrono::steady_clock::now() - start < delay) {
do_strategic_action();
cv::Mat image = ctrler()->get_image();
while (!need_exit() && check_in_battle(image) && std::chrono::steady_clock::now() - start < delay) {
do_strategic_action(image);
std::this_thread::yield();
image = ctrler()->get_image();
}
}
bool asst::BattleProcessTask::check_in_battle(const cv::Mat& reusable, bool weak)
{
LogTraceFunction;
cv::Mat image = reusable.empty() ? ctrler()->get_image() : reusable;
if (weak) {
BattlefieldMatcher analyzer(image);
auto result = analyzer.analyze();
m_in_battle = result.has_value();
if (m_in_battle && !result->pause_button) {
if (check_skip_plot_button(image) && check_in_speed_up(image)) {
speed_up();
}
}
}
else {
check_skip_plot_button(image);
m_in_battle = check_pause_button(image);
}
return m_in_battle;
}

View File

@@ -44,8 +44,6 @@ protected:
bool enter_bullet_time(const std::string& name, const Point& location);
void sleep_and_do_strategy(unsigned millisecond);
virtual bool check_in_battle(const cv::Mat& reusable = cv::Mat(), bool weak = true) override;
battle::copilot::CombatData m_combat_data;
std::unordered_map</*group*/ std::string, /*oper*/ std::string> m_oper_in_group;