fix: 通宝识别失败时放弃通宝 (#15167)

* fix: 通宝识别失败时放弃通宝

* fix: 初始化click_point_fallback

* fix: 通宝交换任务仅尝试2次

* fix: 不小心把调试用的传上去了

* fix: 所有通宝名称识别错误都发送反馈

* i18n: KR

* fix: Tongbao error info tweak

* perf: disable auto clean for Tongbao unknown debug image

* fix: Tongbao info case tweak

---------

Co-authored-by: HX3N <scarlet7518@gmail.com>
This commit is contained in:
travellerse
2025-12-22 23:15:40 +08:00
committed by GitHub
parent 16da7903ba
commit f155bc4867
8 changed files with 40 additions and 8 deletions

View File

@@ -87,6 +87,7 @@ bool asst::RoguelikeCoppersTaskPlugin::_run()
success = handle_pickup_mode();
break;
case CoppersTaskRunMode::EXCHANGE:
m_retry_times = 1; // 交换模式只尝试两次
success = handle_exchange_mode();
break;
}
@@ -120,6 +121,8 @@ bool asst::RoguelikeCoppersTaskPlugin::handle_pickup_mode()
return false;
}
asst::Point click_point_fallback(0, 0);
// 遍历每个检测到的通宝,创建通宝对象
for (size_t i = 0; i < detections.size(); ++i) {
const auto& detection = detections[i];
@@ -129,7 +132,9 @@ bool asst::RoguelikeCoppersTaskPlugin::handle_pickup_mode()
// 根据识别到的名称创建通宝对象
auto copper_opt = create_copper_from_name(detection.name, 1, static_cast<int>(i), false, detection.name_roi);
if (!copper_opt) {
LogError << __FUNCTION__ << "| failed to create copper at position" << i;
LogError << __FUNCTION__ << "| failed to create copper at position" << i << " name:" << detection.name;
click_point_fallback = detection.click_point;
continue;
}
@@ -144,7 +149,13 @@ bool asst::RoguelikeCoppersTaskPlugin::handle_pickup_mode()
if (m_pending_copper.empty()) {
Log.error(__FUNCTION__, "| no valid coppers found for pickup");
return false;
// 如果没有有效通宝,尝试点击最后一个检测到的名称错误的通宝位置作为回退
if (click_point_fallback.x != 0 && click_point_fallback.y != 0) {
LogWarn << __FUNCTION__ << "| clicking fallback point at (" << click_point_fallback.x << ","
<< click_point_fallback.y << ")";
ctrler()->click(click_point_fallback);
return true;
}
}
// 从待选通宝中选择拾取优先级最高的
@@ -517,7 +528,7 @@ std::optional<asst::RoguelikeCopper> asst::RoguelikeCoppersTaskPlugin::create_co
int col,
int row,
bool is_cast,
const Rect& pos) const
const Rect& pos)
{
// 从配置中查找通宝信息
if (auto found_copper = RoguelikeCoppers.find_copper(m_config->get_theme(), name)) {
@@ -538,6 +549,11 @@ std::optional<asst::RoguelikeCopper> asst::RoguelikeCoppersTaskPlugin::create_co
Log.error(__FUNCTION__, std::format("| copper not found in config: {}", name));
// 将识别到的错误的名称发送到 WPF 进行反馈
auto copper_info = basic_info_with_what("RoguelikeCoppersRecognitionError");
copper_info["details"]["recognized_name"] = name;
callback(AsstMsg::SubTaskExtraInfo, copper_info);
// 如果通宝不在配置中,保存调试图像
try {
cv::Mat screen = ctrler()->get_image();
@@ -545,7 +561,7 @@ std::optional<asst::RoguelikeCopper> asst::RoguelikeCoppersTaskPlugin::create_co
cv::Mat screen_draw = screen.clone();
cv::rectangle(screen_draw, cv::Rect(pos.x, pos.y, pos.width, pos.height), cv::Scalar(0, 0, 255), 2);
save_debug_image(screen_draw, "unknown_draw");
save_debug_image(screen_draw, "unknown_draw", false);
}
}
catch (const std::exception& e) {
@@ -596,7 +612,10 @@ void asst::RoguelikeCoppersTaskPlugin::draw_detection_debug(
}
// 保存调试图像到文件
void asst::RoguelikeCoppersTaskPlugin::save_debug_image(const cv::Mat& image, const std::string& suffix) const
void asst::RoguelikeCoppersTaskPlugin::save_debug_image(
const cv::Mat& image,
const std::string& suffix,
bool auto_clean) const
{
try {
const static std::vector<int> jpeg_params = { cv::IMWRITE_JPEG_QUALITY, 95, cv::IMWRITE_JPEG_OPTIMIZE, 1 };
@@ -604,7 +623,7 @@ void asst::RoguelikeCoppersTaskPlugin::save_debug_image(const cv::Mat& image, co
utils::save_debug_image(
image,
utils::path("debug") / "roguelike" / "coppers",
true,
auto_clean,
"roguelikeCoppers debug",
suffix,
"jpeg",

View File

@@ -62,7 +62,7 @@ private:
int row = 0, // 行位置
bool is_cast = false, // 是否已投出
const Rect& pos = Rect() // 位置信息,用于调试
) const;
);
// 调试绘制辅助函数,在图像上绘制检测结果
void draw_detection_debug(
@@ -71,7 +71,7 @@ private:
const cv::Scalar& color) const;
// 保存调试图像到文件
void save_debug_image(const cv::Mat& image, const std::string& suffix) const;
void save_debug_image(const cv::Mat& image, const std::string& suffix, bool auto_clean = true) const;
mutable asst::CoppersTaskRunMode m_run_mode; // 当前运行模式

View File

@@ -1057,6 +1057,7 @@ Right-click to clear inactive jobs</system:String>
<system:String x:Key="BoskyDoubts">Bosky: Doubts</system:String>
<system:String x:Key="BoskyDisaster">Bosky: Turmoil</system:String>
<system:String x:Key="RoguelikeCoppersExchange">Tongbao Exchange: {0} → {1}</system:String>
<system:String x:Key="RoguelikeCoppersRecognitionError">Tongbao recognition failed: "{0}"</system:String>
<system:String x:Key="RoguelikeEvent">Event:&#160;</system:String>
<system:String x:Key="RoguelikeEncounterOptions">Detected {0} options:</system:String>
<system:String x:Key="RoguelikeEncounterEnabledOption">Available option: {0}</system:String>

View File

@@ -1058,6 +1058,7 @@ C:\\leidian\\LDPlayer9
<system:String x:Key="BoskyDoubts">スポット: 雑疑</system:String>
<system:String x:Key="BoskyDisaster">スポット: 禍乱</system:String>
<system:String x:Key="RoguelikeCoppersExchange">通宝交換: {0} → {1}</system:String>
<system:String x:Key="RoguelikeCoppersRecognitionError">通宝認識失敗: 「{0}」</system:String>
<system:String x:Key="RoguelikeEvent">イベント:</system:String>
<system:String x:Key="RoguelikeEncounterOptions">{0} 件の選択肢を検出しました:</system:String>
<system:String x:Key="RoguelikeEncounterEnabledOption">選択可能な選択肢: {0}</system:String>

View File

@@ -1059,6 +1059,7 @@ C:\\leidian\\LDPlayer9
<system:String x:Key="BoskyDoubts">잔식: 의문</system:String>
<system:String x:Key="BoskyDisaster">잔식: 소란</system:String>
<system:String x:Key="RoguelikeCoppersExchange">주화 교환: {0} → {1}</system:String>
<system:String x:Key="RoguelikeCoppersRecognitionError">주화 인식 실패: "{0}"</system:String>
<system:String x:Key="RoguelikeEvent">이벤트:</system:String>
<system:String x:Key="RoguelikeEncounterOptions">선택지 {0}개 감지:</system:String>
<system:String x:Key="RoguelikeEncounterEnabledOption">가능한 선택지: {0}</system:String>

View File

@@ -1058,6 +1058,7 @@ C:\\leidian\\LDPlayer9。\n
<system:String x:Key="BoskyDoubts">节点: 杂疑</system:String>
<system:String x:Key="BoskyDisaster">节点: 灾祸</system:String>
<system:String x:Key="RoguelikeCoppersExchange">通宝交换: {0} → {1}</system:String>
<system:String x:Key="RoguelikeCoppersRecognitionError">通宝识别失败: "{0}"</system:String>
<system:String x:Key="RoguelikeEvent">事件:</system:String>
<system:String x:Key="RoguelikeEncounterOptions">识别到 {0} 个选项:</system:String>
<system:String x:Key="RoguelikeEncounterEnabledOption">可选选项: {0}</system:String>

View File

@@ -1059,6 +1059,7 @@ C:\\leidian\\LDPlayer9。\n
<system:String x:Key="BoskyDoubts">節點: 雜疑</system:String>
<system:String x:Key="BoskyDisaster">節點: 災禍</system:String>
<system:String x:Key="RoguelikeCoppersExchange">通寶交換: {0} → {1}</system:String>
<system:String x:Key="RoguelikeCoppersRecognitionError">通寶識別失敗: "{0}"</system:String>
<system:String x:Key="RoguelikeEvent">事件:</system:String>
<system:String x:Key="RoguelikeEncounterOptions">識別到 {0} 個選項:</system:String>
<system:String x:Key="RoguelikeEncounterEnabledOption">可選選項: {0}</system:String>

View File

@@ -1126,6 +1126,14 @@ public class RoguelikeSettingsUserControlModel : TaskViewModel
break;
}
case "RoguelikeCoppersRecognitionError":
{
var recognizedName = subTaskDetails!["recognized_name"]?.ToString() ?? "Unknown";
var message = string.Format(LocalizationHelper.GetString("RoguelikeCoppersRecognitionError"), recognizedName);
Instances.TaskQueueViewModel.AddLog(message, UiLogColor.Error);
break;
}
case "RoguelikeCoppersExchangeInfo":
{
var toDiscard = subTaskDetails!["to_discard"]?.ToString() ?? "Unknown";