mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-19 10:32:19 +08:00
生息演算 添加黑市npc对话支持
This commit is contained in:
@@ -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": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user