生息演算 添加黑市npc对话支持

This commit is contained in:
wangli
2023-02-05 15:53:30 +08:00
committed by LambdaLe
parent 52f9664e97
commit 8793b2ffab
3 changed files with 179 additions and 5 deletions

View File

@@ -10707,5 +10707,49 @@
"next": [
"Reclamation@ExitAlgorithm"
]
},
"Reclamation@Liaison":{
"algorithm": "OcrDetect",
"roi": [
0, 141, 179, 130
],
"text": [
"联络员"
]
},
"Reclamation@BalckMarketDialogOption":{
"algorithm": "OcrDetect",
"roi": [
721, 78, 543, 492
],
"text": [],
"postDelay": 500
},
"Reclamation@BuyWaterProcedure":{
"algorithm": "OcrDetect",
"text": [
"Skip",
"建材",
"清水",
"Skip"
]
},
"Reclamation@SkillReadyRoleOffset":{
"Doc": "技能准备完成距离npc中心的偏移",
"template": "empty.png",
"specialParams": [
100
]
},
"Reclamation@BattleSkillReadyOnClick": {
"baseTask": "BattleSkillReadyOnClick",
"template": "BattleSkillReadyOnClick.png",
"roi": [
439, 76, 841, 644
]
},
"Reclamation@DialogSkip":{
"baseTask": "Reclamation@SkipAnnounce",
"next": []
}
}

View File

@@ -8,8 +8,10 @@
#include "Utils/Logger.hpp"
#include "Vision/OcrImageAnalyzer.h"
#include "Vision/MatchImageAnalyzer.h"
#include "Vision/Miscellaneous/BattleSkillReadyImageAnalyzer.h"
#include "Config/TaskData.h"
asst::ReclamationBattlePlugin::ReclamationBattlePlugin(const AsstCallback& callback, Assistant* inst,
std::string_view task_chain)
: AbstractTaskPlugin(callback, inst, task_chain), BattleHelper(inst)
@@ -37,6 +39,16 @@ bool asst::ReclamationBattlePlugin::_run()
wait_until_start(false);
return quit_action();
}
bool asst::ReclamationBattlePlugin::do_strategic_action(const cv::Mat&)
{
return true;
}
bool asst::ReclamationBattlePlugin::quit_action()
{
while (!need_exit()) {
int retry = 0;
while (!need_exit()) {
@@ -44,7 +56,7 @@ bool asst::ReclamationBattlePlugin::_run()
bool stage2 = ProcessTask(*this, { "Reclamation@ExitLevelConfirm" }).set_retry_times(3).run();
Log.info(__FUNCTION__, "| click exit level perform ", stage1, stage2);
if (stage2) break;
retry++; // stage1==true&&stage2==false应该是手动按了确定或是没按到退出
retry++; // stage1==true&&stage2==false应该是手动按了确定或是没按到退出
if ((!stage1 && !stage2) || retry > 5) {
// 已经到了结算界面,或是用户手动操作了
Log.error(__FUNCTION__, "| fail to operate");
@@ -53,9 +65,9 @@ bool asst::ReclamationBattlePlugin::_run()
}
sleep(Task.get("Reclamation@BattleStart")->special_params.front());
const auto img = ctrler()->get_image();
bool check1 = check_in_battle(img, false);
bool check1 = check_in_battle(img, false);
OcrImageAnalyzer confirmAnalyzer(img);
confirmAnalyzer.set_task_info("Reclamation@ExitLevelConfirm");
@@ -74,11 +86,121 @@ bool asst::ReclamationBattlePlugin::_run()
break;
}
}
return true;
}
bool asst::ReclamationBattlePlugin::do_strategic_action(const cv::Mat&)
bool asst::ReclamationBattlePlugin::buy_water()
{
if (!communicate_with(Task.get<OcrTaskInfo>("Reclamation@Liaison")->text.front())) return false;
if (!do_dialog_procedure(Task.get<OcrTaskInfo>("Reclamation@BuyWaterProcedure")->text)) return false;
return true;
}
bool asst::ReclamationBattlePlugin::communicate_with(const std::string& npcName)
{
// 在存在两个及以上npc时地图会移动从上到下、从下到上各试一次还不行算了
if (communicate_with_aux(npcName, [](const MatchRect& l, const MatchRect& r) {
return l.rect.y < r.rect.y || (l.rect.y == r.rect.y && l.rect.x < r.rect.x);
}))
return true;
if (communicate_with_aux(npcName, [](const MatchRect& l, const MatchRect& r) {
return l.rect.y > r.rect.y || (l.rect.y == r.rect.y && l.rect.x > r.rect.x);
}))
return true;
Log.info(__FUNCTION__, " | ", "fail to communicate with npc");
return false;
}
bool asst::ReclamationBattlePlugin::communicate_with_aux(const std::string& npcName, std::function<bool(const MatchRect&, const MatchRect&)> orderComp)
{
auto image = ctrler()->get_image();
BattleSkillReadyImageAnalyzer skillReadyAnalyzer(image);
if (!skillReadyAnalyzer.analyze()) {
Log.info(__FUNCTION__, " | ", "no ready skills");
return false;
}
std::vector<MatchRect> skill_results = skillReadyAnalyzer.get_result();
std::sort(skill_results.begin(), skill_results.end(), orderComp);
for (const auto& [score, rect] : skill_results) {
Rect center(rect.x + rect.width / 2,
rect.y + rect.height / 2 + Task.get("Reclamation@SkillReadyRoleOffset")->special_params.front(), 5,
5);
const auto use_oper_task_ptr = Task.get("BattleUseOper");
ctrler()->click(center);
sleep(use_oper_task_ptr->pre_delay);
image = ctrler()->get_image();
OcrImageAnalyzer npcNameAnalyzer(image);
npcNameAnalyzer.set_task_info("Reclamation@Liaison");
npcNameAnalyzer.set_required({});
if (!npcNameAnalyzer.analyze()) {
// 地图发生了移动
Log.info(__FUNCTION__, " | ", "map moved ");
break;
}
if (npcNameAnalyzer.get_result().front() != npcName) {
// npc名称不正确
Log.info(__FUNCTION__, " | ", "npc name not match ", npcNameAnalyzer.get_result().front());
cancel_oper_selection();
continue;
}
ProcessTask skill_task(this_task(), { "Reclamation@BattleSkillReadyOnClick" });
skill_task.set_task_delay(0);
bool ret = skill_task.set_retry_times(5).run();
if (!ret) {
cancel_oper_selection();
Log.info(__FUNCTION__, " | ", "fail to click skill of npc");
return false;
}
return true;
}
return false;
}
bool asst::ReclamationBattlePlugin::do_dialog_procedure(const std::vector<std::string>& procedure)
{
for (auto& step : procedure) {
if (step == "Skip") {
ProcessTask(this_task(), { "Reclamation@DialogSkip" }).set_task_delay(0).set_retry_times(5).run();
}
else {
const int max_retry = 5;
int retry = 0;
bool succeed = false;
while (!need_exit()){
if (retry == max_retry) break;
const auto& image = ctrler()->get_image();
OcrImageAnalyzer dialogAnalyzer(image);
dialogAnalyzer.set_task_info("Reclamation@BalckMarketDialogOption");
dialogAnalyzer.set_required({ step });
if (!dialogAnalyzer.analyze()) {
if (succeed) {
break;
}
else {
retry++;
continue;
}
}
const auto& rect = dialogAnalyzer.get_result().front().rect;
ctrler()->click(rect);
Log.info(__FUNCTION__, " | ", "perform dialog option ", step);
sleep(Task.get("Reclamation@BalckMarketDialogOption")->post_delay);
succeed = true;
}
if (retry == max_retry) {
Log.info(__FUNCTION__, " | ", "fail to perform dialog option ", step);
return false;
}
}
}
return true;
}

View File

@@ -17,5 +17,13 @@ namespace asst
virtual bool _run() override;
virtual bool do_strategic_action(const cv::Mat& reusable = cv::Mat()) override;
virtual AbstractTask& this_task() override { return *this; }
bool quit_action();
bool buy_water();
bool communicate_with(const std::string& npcName);
bool communicate_with_aux(const std::string& npcName,
std::function<bool(const MatchRect&, const MatchRect&)> orderComp);
bool do_dialog_procedure(const std::vector<std::string>& procedure);
};
}