diff --git a/docs/集成文档.md b/docs/集成文档.md index 684a8c8cf0..11c57caafe 100644 --- a/docs/集成文档.md +++ b/docs/集成文档.md @@ -130,6 +130,10 @@ TaskId ASSTAPI AsstAppendTask(AsstHandle handle, const char* type, const char* p "skill": int, // 使用哪个技能,取值范围 [1, 3],可选项,默认 1 // 若设置为 3, 当 3 技能不可用时,会选择 2 技能 // 同理若设置为 2, 当 2 技能不可用时,会选择 1 技能(好像没有这种 case?) + "skill_usage": int // 技能用法,可选,默认 0 + // 0 - 好了就用,有多少次用多少次(例如干员 棘刺 3 技能) + // 1 - 好了就用,仅使用一次(例如干员 山 2 技能) + // 2 - 关键时刻使用(例如干员 梓兰、芙蓉) }, ... ] diff --git a/resource/tasks.json b/resource/tasks.json index ef67cb1c71..b45ad36cd4 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -3234,6 +3234,16 @@ 100 ] }, + "BattleOperName": { + "algorithm": "OcrDetect", + "text": [], + "roi": [ + 0, + 160, + 180, + 60 + ] + }, "BattleUseOper": { "algorithm": "JustReturn", "preDelay": 500, @@ -3925,6 +3935,7 @@ "Roguelike1RecruitData": { "algorithm": "OcrDetect", "text": [], + "Doc": "该任务的 ocrReplace 被所有涉及干员名的识别任务服用", "ocrReplace": [ [ "白面.+", @@ -4619,20 +4630,6 @@ "algorithm": "OcrDetect", "text": [], "action": "DoNothing", - "ocrReplace": [ - [ - "白面.+", - "白面鸮" - ], - [ - "蛇居箱", - "蛇屠箱" - ], - [ - ".+刺", - "棘刺" - ] - ], "rectMove": [ 150, -30, diff --git a/src/MeoAssistant/AsstTypes.h b/src/MeoAssistant/AsstTypes.h index cff70891ef..8d0589e90f 100644 --- a/src/MeoAssistant/AsstTypes.h +++ b/src/MeoAssistant/AsstTypes.h @@ -88,6 +88,10 @@ namespace asst { return x <= rhs.x && y <= rhs.y && (x + width) >= (rhs.x + rhs.width) && (y + height) >= (rhs.y + rhs.height); } + bool include(const Point& rhs) const noexcept + { + return x <= rhs.x && y <= rhs.y && (x + width) >= rhs.x && (y + height) >= rhs.y; + } std::string to_string() const { return "[ " + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(width) + ", " + std::to_string(height) + " ]"; diff --git a/src/MeoAssistant/Resource.cpp b/src/MeoAssistant/Resource.cpp index ec1e987ab7..0efbad017e 100644 --- a/src/MeoAssistant/Resource.cpp +++ b/src/MeoAssistant/Resource.cpp @@ -76,8 +76,6 @@ bool asst::Resource::load(const std::string& dir) overload = true; } - const auto& opt = m_general_cfg_unique_ins.get_options(); - /* 加载模板图片资源 */ // task所需要的模板资源 m_templ_resource_unique_ins.append_load_required(TaskData::get_instance().get_templ_required()); diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp index 35926dec2b..c7fbb6d826 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp @@ -24,6 +24,11 @@ bool asst::RoguelikeBattleTaskPlugin::verify(AsstMsg msg, const json::value& det } } +void asst::RoguelikeBattleTaskPlugin::set_skill_usage(SkillUsageMap usage_map) +{ + m_skill_usage = std::move(usage_map); +} + void asst::RoguelikeBattleTaskPlugin::set_stage_name(std::string stage) { m_stage_name = std::move(stage); @@ -41,7 +46,7 @@ bool asst::RoguelikeBattleTaskPlugin::_run() while (!need_exit()) { // 不在战斗场景,且已使用过了干员,说明已经打完了,就结束循环 - if (!auto_battle() && m_used_opers) { + if (!auto_battle() && m_opers_used) { break; } } @@ -78,6 +83,7 @@ bool asst::RoguelikeBattleTaskPlugin::get_stage_info() continue; } m_side_tile_info = std::move(side_info); + m_normal_tile_info = tile.calc(tr.text, false); m_stage_name = tr.text; calced = true; break; @@ -140,20 +146,46 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() return false; } - if (int hp = battle_analyzer.get_hp(); - hp != 0) { - bool used_skills = false; - if (hp < m_pre_hp) { // 说明漏怪了,漏怪就开技能( - for (const Rect& rect : battle_analyzer.get_ready_skills()) { - used_skills = true; - if (!use_skill(rect)) { - break; - } + //if (int hp = battle_analyzer.get_hp(); + // hp != 0) { + // bool used_skills = false; + // if (hp < m_pre_hp) { // 说明漏怪了,漏怪就开技能( + // for (const Rect& rect : battle_analyzer.get_ready_skills()) { + // used_skills = true; + // if (!use_skill(rect)) { + // break; + // } + // } + // } + // m_pre_hp = hp; + // if (used_skills) { + // return true; + // } + //} + + for (const Rect& rect : battle_analyzer.get_ready_skills()) { + // 找出这个可以使用的技能是哪个干员的(根据之前放干员的位置) + std::string name = "NotFound"; + for (const auto& [loc, oper_name] : m_used_tiles) { + auto point = m_normal_tile_info[loc].pos; + if (rect.include(point)) { + name = oper_name; + break; } } - m_pre_hp = hp; - if (used_skills) { + + auto& usage = m_skill_usage[name]; + Log.info("Oper", name, ", skill usage", static_cast(usage)); + switch (usage) { + case SkillUsage::Once: + use_skill(rect); + usage = SkillUsage::NotUse; return true; + break; + case SkillUsage::Possibly: + use_skill(rect); + return true; + break; } } @@ -200,6 +232,19 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() m_ctrler->click(opt_oper.rect); sleep(use_oper_task_ptr->pre_delay); + OcrImageAnalyzer oper_name_analyzer(m_ctrler->get_image()); + oper_name_analyzer.set_task_info(Task.get("BattleOperName")); + oper_name_analyzer.set_replace( + std::dynamic_pointer_cast( + Task.get("Roguelike1RecruitData")) + ->replace_map); + + std::string oper_name = "Unknown"; + if (oper_name_analyzer.analyze()) { + oper_name_analyzer.sort_result_by_score(); + oper_name = oper_name_analyzer.get_result().front().text; + } + // 将干员拖动到场上 Loc loc = Loc::All; switch (opt_oper.role) { @@ -259,8 +304,8 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() m_ctrler->swipe(placed_point, end_point, swipe_oper_task_ptr->rear_delay); - m_used_tiles.emplace(placed_loc); - m_used_opers = true; + m_used_tiles.emplace(placed_loc, oper_name); + m_opers_used = true; ++m_cur_home_index; return true; @@ -283,7 +328,7 @@ bool asst::RoguelikeBattleTaskPlugin::use_skill(const asst::Rect& rect) void asst::RoguelikeBattleTaskPlugin::clear() { - m_used_opers = false; + m_opers_used = false; m_pre_hp = 0; m_homes.clear(); m_cur_home_index = 0; diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.h b/src/MeoAssistant/RoguelikeBattleTaskPlugin.h index 9c7cd00da9..b0dd7fecca 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.h +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.h @@ -7,16 +7,26 @@ namespace asst { + enum class SkillUsage + { + Possibly = 0, // 有就用,例如干员 棘刺 3 技能 + Once = 1, // 只用一次,例如干员 银灰 2技能 + InTime = 2, // 关键时刻使用,例如干员 假日威龙陈 3 技能 + NotUse + }; class RoguelikeBattleTaskPlugin : public AbstractTaskPlugin { using Loc = asst::TilePack::BuildableType; using Role = asst::BattleImageAnalyzer::Role; + public: + using SkillUsageMap = std::unordered_map; public: using AbstractTaskPlugin::AbstractTaskPlugin; virtual ~RoguelikeBattleTaskPlugin() = default; virtual bool verify(AsstMsg msg, const json::value& details) const override; + void set_skill_usage(SkillUsageMap usage_map); void set_stage_name(std::string stage); protected: @@ -36,14 +46,16 @@ namespace asst // 返回滑动的方向 Point calc_direction(Point loc, Role role); - bool m_used_opers = false; + bool m_opers_used = false; int m_pre_hp = 0; std::unordered_map m_side_tile_info; + std::unordered_map m_normal_tile_info; std::vector m_homes; size_t m_cur_home_index = 0; - std::unordered_set m_used_tiles; + std::unordered_map m_used_tiles; std::string m_stage_name; + SkillUsageMap m_skill_usage; }; } diff --git a/src/MeoAssistant/RoguelikeSkillSelectionImageAnalyzer.cpp b/src/MeoAssistant/RoguelikeSkillSelectionImageAnalyzer.cpp index 41bec32163..11c5cb63d2 100644 --- a/src/MeoAssistant/RoguelikeSkillSelectionImageAnalyzer.cpp +++ b/src/MeoAssistant/RoguelikeSkillSelectionImageAnalyzer.cpp @@ -39,6 +39,10 @@ std::string asst::RoguelikeSkillSelectionImageAnalyzer::name_analyze(const Rect& auto name_task_ptr = Task.get("Roguelike1SkillSelectionName"); analyzer.set_task_info(name_task_ptr); analyzer.set_image(m_image, roi.move(name_task_ptr->rect_move)); + analyzer.set_replace( + std::dynamic_pointer_cast( + Task.get("Roguelike1RecruitData")) + ->replace_map); if (!analyzer.analyze()) { return std::string(); diff --git a/src/MeoAssistant/RoguelikeTask.cpp b/src/MeoAssistant/RoguelikeTask.cpp index 329f501f32..7cd3cc34b2 100644 --- a/src/MeoAssistant/RoguelikeTask.cpp +++ b/src/MeoAssistant/RoguelikeTask.cpp @@ -5,6 +5,7 @@ #include "RoguelikeBattleTaskPlugin.h" #include "RoguelikeRecruitTaskPlugin.h" #include "RoguelikeSkillSelectionTaskPlugin.h" +#include "RoguelikeBattleTaskPlugin.h" #include "Logger.hpp" @@ -16,7 +17,9 @@ asst::RoguelikeTask::RoguelikeTask(AsstCallback callback, void* callback_arg) .set_retry_times(50); m_roguelike_task_ptr->regiseter_plugin(); - m_roguelike_task_ptr->regiseter_plugin(); + + m_battle_task_ptr = m_roguelike_task_ptr->regiseter_plugin(); + m_recruit_task_ptr = m_roguelike_task_ptr->regiseter_plugin(); m_recruit_task_ptr->set_retry_times(2); @@ -41,6 +44,7 @@ bool asst::RoguelikeTask::set_params(const json::value& params) std::vector opers_vec; RoguelikeSkillSelectionTaskPlugin::SkillMap skill_map; + RoguelikeBattleTaskPlugin::SkillUsageMap usage_map; for (auto& oper : params.at("opers").as_array()) { if (!oper.contains("name") || !oper.at("name").is_string()) { @@ -53,6 +57,9 @@ bool asst::RoguelikeTask::set_params(const json::value& params) std::string name = oper.at("name").as_string(); opers_vec.emplace_back(name); skill_map.emplace(name, skill); + + auto usage = static_cast(oper.get("skill_usage", 0)); + usage_map.emplace(name, usage); } skill_map.emplace("Unknown", 3); @@ -74,5 +81,7 @@ bool asst::RoguelikeTask::set_params(const json::value& params) m_recruit_task_ptr->set_opers(std::move(opers_vec)); m_skill_task_ptr->set_skill_map(std::move(skill_map)); + m_battle_task_ptr->set_skill_usage(std::move(usage_map)); + return true; } diff --git a/src/MeoAssistant/RoguelikeTask.h b/src/MeoAssistant/RoguelikeTask.h index 447f448924..dccb5fbed1 100644 --- a/src/MeoAssistant/RoguelikeTask.h +++ b/src/MeoAssistant/RoguelikeTask.h @@ -6,6 +6,7 @@ namespace asst class ProcessTask; class RoguelikeRecruitTaskPlugin; class RoguelikeSkillSelectionTaskPlugin; + class RoguelikeBattleTaskPlugin; class RoguelikeTask : public PackageTask { @@ -21,5 +22,6 @@ namespace asst std::shared_ptr m_roguelike_task_ptr = nullptr; std::shared_ptr m_recruit_task_ptr = nullptr; std::shared_ptr m_skill_task_ptr = nullptr; + std::shared_ptr m_battle_task_ptr = nullptr; }; } diff --git a/tools/TestCaller/main.cpp b/tools/TestCaller/main.cpp index b0b4e92e91..28e8cf0bf9 100644 --- a/tools/TestCaller/main.cpp +++ b/tools/TestCaller/main.cpp @@ -24,7 +24,7 @@ int main(int argc, char** argv) return -1; } - bool connected = AsstConnect(ptr, "adb", "127.0.0.1:7555", ""); + bool connected = AsstConnect(ptr, "adb", "127.0.0.1:5555", ""); if (!connected) { std::cerr << "connect failed" << std::endl; AsstDestroy(ptr); @@ -37,11 +37,11 @@ int main(int argc, char** argv) //AsstAppendTask(ptr, "StartUp", R"({})"); - AsstAppendTask(ptr, "Fight", R"( -{ - "stage": "" -} - )"); +// AsstAppendTask(ptr, "Fight", R"( +//{ +// "stage": "CE-5" +//} +// )"); // AsstAppendTask(ptr, "Recruit", R"( //{ @@ -72,21 +72,25 @@ int main(int argc, char** argv) //)"); // AsstAppendTask(ptr, "Award", R"({})"); // - // AsstAppendTask(ptr, "Roguelike", R"( - //{ - // "opers": [ - // { - // "name": "帕拉斯" - // }, - // { - // "name": "梓兰" - // }, - // { - // "name": "安赛尔" - // } - // ] - //} - //)"); + AsstAppendTask(ptr, "Roguelike", R"( + { + "opers": [ + { + "name": "棘刺", + "skill": 3, + "skill_usage": 1 + }, + { + "name": "梓兰" + }, + { + "name": "芙蓉" + } + ] + } + )"); + + //AsstAppendTask(ptr, "Debug", R"({})"); AsstStart(ptr);