feat: 线索交流时先移除所有放置的线索 (#16054)
* feat: 线索交流时先移除所有放置的线索 * feat: 线索过多时向下滑动线索列表 * feat: 优化重试机制以处理线索过多情况 * perf: 优化移除线索逻辑 * fix: 线索板为空时移除线索视为成功
@@ -2937,6 +2937,57 @@
|
||||
"roi": [1163, 0, 117, 133],
|
||||
"next": ["Stop"]
|
||||
},
|
||||
"InfrastClueVacancy1": {
|
||||
"template": "ClueVacancy1.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [0, 120, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancy2": {
|
||||
"template": "ClueVacancy2.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [200, 195, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancy3": {
|
||||
"template": "ClueVacancy3.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [400, 100, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancy4": {
|
||||
"template": "ClueVacancy4.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [650, 150, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancy5": {
|
||||
"template": "ClueVacancy5.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [300, 420, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancy6": {
|
||||
"template": "ClueVacancy6.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [500, 350, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancy7": {
|
||||
"template": "ClueVacancy7.png",
|
||||
"templThreshold": 0.75,
|
||||
"roi": [50, 380, 500, 195],
|
||||
"postDelay": 500
|
||||
},
|
||||
"InfrastClueVacancyPin":{
|
||||
"template": "ClueVacancyPin.png",
|
||||
"roi":[854, 121, 152, 594],
|
||||
"maskRange": [1, 255]
|
||||
},
|
||||
"InfrastReceptionIcon": {
|
||||
"template": "InfrastReceptionIcon.png",
|
||||
"roi": [340, 0, 210, 75]
|
||||
},
|
||||
"InfrastClueVacancyNo1": {
|
||||
"template": "ClueVacancyNo1.png",
|
||||
"templThreshold": 0.75,
|
||||
@@ -4142,6 +4193,11 @@
|
||||
"specificRect": [1080, 4, 1, 1],
|
||||
"rectMove": [650, 4, 1, 1]
|
||||
},
|
||||
"InfrastClueListSwipeToTheBottomOnTheRight": {
|
||||
"baseTask": "SlowlySwipeToTheDown",
|
||||
"specificRect": [1080, 300, 20, 20],
|
||||
"rectMove": [1080, 150, 20, 20]
|
||||
},
|
||||
"InfrastOperListSwipeToTheLeft": {
|
||||
"baseTask": "SwipeToTheLeft",
|
||||
"specificRect": [400, 350, 20, 20],
|
||||
|
||||
BIN
resource/template/InfrastPic/Clue/ClueVacancy1.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancy2.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancy3.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancy4.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancy5.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancy6.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancy7.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
resource/template/InfrastPic/Clue/ClueVacancyPin.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
resource/template/InfrastPic/Clue/InfrastReceptionIcon.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
@@ -160,6 +160,69 @@ bool asst::InfrastReceptionTask::use_clue()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asst::InfrastReceptionTask::remove_clue()
|
||||
{
|
||||
LogTraceFunction;
|
||||
const static std::vector<std::string> clue_suffix = { "1", "2", "3", "4", "5", "6", "7" };
|
||||
|
||||
cv::Mat image = ctrler()->get_image();
|
||||
|
||||
// 分析一下哪些线索已经放上了
|
||||
InfrastClueVacancyImageAnalyzer vacancy_analyzer(image);
|
||||
|
||||
vacancy_analyzer.set_to_be_analyzed(clue_suffix);
|
||||
vacancy_analyzer.analyze();
|
||||
|
||||
const auto& vacancy = vacancy_analyzer.get_vacancy();
|
||||
// 没有已放置线索时视为成功,避免中断后续快捷置入流程
|
||||
if (vacancy.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
for (const auto& id : vacancy | std::views::keys) {
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
Log.trace("InfrastReceptionTask | Vacancy", id);
|
||||
|
||||
// 点击已放上的线索
|
||||
Rect click_rect = vacancy.at(id);
|
||||
ret &= ctrler()->click(click_rect);
|
||||
sleep(500);
|
||||
|
||||
bool pin_found = false;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
}
|
||||
Matcher pin_analyzer(ctrler()->get_image());
|
||||
pin_analyzer.set_task_info("InfrastClueVacancyPin");
|
||||
|
||||
if (auto pin_res = pin_analyzer.analyze()) {
|
||||
pin_found = true;
|
||||
ctrler()->click(pin_res->rect);
|
||||
sleep(500);
|
||||
break;
|
||||
}
|
||||
// 向下滑动一点,可能线索比较多
|
||||
swipe_to_the_bottom_of_clue_list_on_the_right();
|
||||
}
|
||||
ret &= pin_found;
|
||||
|
||||
// 移除线索后点击会客室图标来关闭侧边栏
|
||||
Matcher confirm_analyzer(ctrler()->get_image());
|
||||
confirm_analyzer.set_task_info("InfrastReceptionIcon");
|
||||
|
||||
if (auto confirm_res = confirm_analyzer.analyze()) {
|
||||
ret &= ctrler()->click(confirm_res->rect);
|
||||
sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool asst::InfrastReceptionTask::proc_clue_vacancy()
|
||||
{
|
||||
LogTraceFunction;
|
||||
@@ -170,6 +233,15 @@ bool asst::InfrastReceptionTask::proc_clue_vacancy()
|
||||
|
||||
// 优先检测官服新增的“快捷置入”按钮,如果存在则尝试根据数字与空位一致时批量置入
|
||||
if (ProcessTask(*this, { "InfrastClueQuickInsert" }).set_retry_times(3).run()) {
|
||||
// 先把线索都移除掉,避免因快捷赠送重复线索无法识别线索版上的线索导致线索达到上限,而无法获得新线索
|
||||
if (!remove_clue()) {
|
||||
Log.warn(__FUNCTION__, "| remove_clue failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 移除线索会改变界面,重新抓取截图供后续分析使用
|
||||
image = ctrler()->get_image();
|
||||
|
||||
InfrastClueVacancyImageAnalyzer vacancy_analyzer(image);
|
||||
vacancy_analyzer.set_to_be_analyzed(clue_suffix);
|
||||
vacancy_analyzer.analyze();
|
||||
@@ -323,3 +395,10 @@ bool asst::InfrastReceptionTask::shift()
|
||||
click_confirm_button();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asst::InfrastReceptionTask::swipe_to_the_bottom_of_clue_list_on_the_right()
|
||||
{
|
||||
bool ret = ProcessTask(*this, { "InfrastClueListSwipeToTheBottomOnTheRight" }).run();
|
||||
sleep(500);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -30,12 +30,15 @@ private:
|
||||
bool get_friend_clue();
|
||||
bool get_self_clue();
|
||||
bool use_clue();
|
||||
bool remove_clue();
|
||||
bool proc_clue_vacancy();
|
||||
bool unlock_clue_exchange();
|
||||
bool back_to_reception_main();
|
||||
bool send_clue();
|
||||
bool shift();
|
||||
|
||||
bool swipe_to_the_bottom_of_clue_list_on_the_right();
|
||||
|
||||
bool m_receive_message_board = true;
|
||||
bool m_enable_clue_exchange = true;
|
||||
bool m_send_clue = true;
|
||||
|
||||