diff --git a/src/MaaCore/Task/BattleHelper.cpp b/src/MaaCore/Task/BattleHelper.cpp index 0faa69bc66..0076fc5fd6 100644 --- a/src/MaaCore/Task/BattleHelper.cpp +++ b/src/MaaCore/Task/BattleHelper.cpp @@ -116,7 +116,7 @@ bool asst::BattleHelper::speed_up() return ProcessTask(this_task(), { "BattleSpeedUp" }).run(); } -bool asst::BattleHelper::update_deployment(bool init) +bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable) { LogTraceFunction; @@ -124,18 +124,11 @@ bool asst::BattleHelper::update_deployment(bool init) wait_for_start(); } - cv::Mat image = m_inst_helper.ctrler()->get_image(); + cv::Mat image = init || reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable; if (init) { auto draw_future = std::async(std::launch::async, [&]() { save_map(image); }); - - // 识别一帧总击杀数 - BattleImageAnalyzer kills_analyzer(image); - kills_analyzer.set_target(BattleImageAnalyzer::Target::Kills); - if (kills_analyzer.analyze()) { - m_kills = kills_analyzer.get_kills(); - m_total_kills = kills_analyzer.get_total_kills(); - } + update_kills(image); } BattleImageAnalyzer oper_analyzer(image); @@ -243,6 +236,34 @@ bool asst::BattleHelper::update_deployment(bool init) return true; } +bool asst::BattleHelper::update_kills(const cv::Mat& reusable) +{ + cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable; + BattleImageAnalyzer analyzer(image); + if (m_total_kills) { + analyzer.set_pre_total_kills(m_total_kills); + } + analyzer.set_target(BattleImageAnalyzer::Target::Kills); + if (!analyzer.analyze()) { + return false; + } + m_kills = analyzer.get_kills(); + m_total_kills = analyzer.get_total_kills(); + return true; +} + +bool asst::BattleHelper::update_cost(const cv::Mat& reusable) +{ + cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable; + BattleImageAnalyzer analyzer(image); + analyzer.set_target(BattleImageAnalyzer::Target::Cost); + if (!analyzer.analyze()) { + return false; + } + m_cost = analyzer.get_cost(); + return true; +} + bool asst::BattleHelper::deploy_oper(const std::string& name, const Point& loc, DeployDirection direction) { LogTraceFunction; @@ -383,39 +404,42 @@ bool asst::BattleHelper::wait_for_end() return true; } -bool asst::BattleHelper::use_all_ready_skill() +bool asst::BattleHelper::use_all_ready_skill(const cv::Mat& reusable) { bool used = false; + cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable; for (const auto& [name, loc] : m_battlefield_opers) { auto& usage = m_skill_usage[name]; if (usage != SkillUsage::Possibly && usage != SkillUsage::Once) { continue; } - if (!check_and_use_skill(loc)) { + if (!check_and_use_skill(loc, image)) { continue; } used = true; if (usage == SkillUsage::Once) { usage = SkillUsage::OnceUsed; } + image = m_inst_helper.ctrler()->get_image(); } return used; } -bool asst::BattleHelper::check_and_use_skill(const std::string& name) +bool asst::BattleHelper::check_and_use_skill(const std::string& name, const cv::Mat& reusable) { auto oper_iter = m_battlefield_opers.find(name); if (oper_iter == m_battlefield_opers.cend()) { Log.error("No oper", name); return false; } - return check_and_use_skill(oper_iter->second); + return check_and_use_skill(oper_iter->second, reusable); } -bool asst::BattleHelper::check_and_use_skill(const Point& loc) +bool asst::BattleHelper::check_and_use_skill(const Point& loc, const cv::Mat& reusable) { - BattleSkillReadyImageAnalyzer skill_analyzer(m_inst_helper.ctrler()->get_image()); + cv::Mat image = reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable; + BattleSkillReadyImageAnalyzer skill_analyzer(image); auto target_iter = m_normal_tile_info.find(loc); if (target_iter == m_normal_tile_info.end()) { diff --git a/src/MaaCore/Task/BattleHelper.h b/src/MaaCore/Task/BattleHelper.h index 21f8f7e822..a1ecbab0e9 100644 --- a/src/MaaCore/Task/BattleHelper.h +++ b/src/MaaCore/Task/BattleHelper.h @@ -34,7 +34,9 @@ namespace asst bool pause(); bool speed_up(); - bool update_deployment(bool init = false); + bool update_deployment(bool init = false, const cv::Mat& reusable = cv::Mat()); + bool update_kills(const cv::Mat& reusable = cv::Mat()); + bool update_cost(const cv::Mat& reusable = cv::Mat()); bool deploy_oper(const std::string& name, const Point& loc, battle::DeployDirection direction); bool retreat_oper(const std::string& name); @@ -44,9 +46,9 @@ namespace asst bool check_pause_button(); bool wait_for_start(); bool wait_for_end(); - bool use_all_ready_skill(); - bool check_and_use_skill(const std::string& name); - bool check_and_use_skill(const Point& loc); + bool use_all_ready_skill(const cv::Mat& reusable = cv::Mat()); + bool check_and_use_skill(const std::string& name, const cv::Mat& reusable = cv::Mat()); + bool check_and_use_skill(const Point& loc, const cv::Mat& reusable = cv::Mat()); void save_map(const cv::Mat& image); bool click_oper_on_deployment(const std::string& name); @@ -69,6 +71,7 @@ namespace asst /* 实时更新的数据 */ int m_kills = 0; int m_total_kills = 0; + int m_cost = 0; std::map m_all_deployment_avatars; std::map m_cur_deployment_opers; diff --git a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp index e0cb70f624..fb98635abe 100644 --- a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp +++ b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp @@ -213,91 +213,79 @@ void asst::BattleProcessTask::notify_action(const battle::copilot::Action& actio bool asst::BattleProcessTask::wait_condition(const Action& action) { - // 计算初始状态 - int cost_base = -1; - // int cooling_base = -1; + cv::Mat image; + auto update_image_if_empty = [&]() { + if (image.empty()) image = ctrler()->get_image(); + }; + auto use_all_ready_skill_then_update_image = [&]() { + use_all_ready_skill(image); + image = ctrler()->get_image(); + }; if (action.cost_changes != 0) { - BattleImageAnalyzer analyzer(ctrler()->get_image()); - analyzer.set_target(BattleImageAnalyzer::Target::Cost); - if (analyzer.analyze()) { - cost_base = analyzer.get_cost(); - } - } - // if (action.cooling != 0) { - // BattleImageAnalyzer analyzer(image); - // analyzer.set_target(BattleImageAnalyzer::Target::Oper); - // if (analyzer.analyze()) { - // cooling_base = - // ranges::count_if(analyzer.get_opers(), [](const auto& oper) -> bool { return oper.cooling; }); - // } - // } + update_image_if_empty(); + update_cost(image); + int pre_cost = m_cost; - // 计算击杀数 - while (!need_exit() && m_kills < action.kills) { - BattleImageAnalyzer analyzer(ctrler()->get_image()); - if (m_total_kills) { - analyzer.set_pre_total_kills(m_total_kills); - } - analyzer.set_target(BattleImageAnalyzer::Target::Kills); - if (analyzer.analyze()) { - m_kills = analyzer.get_kills(); - m_total_kills = analyzer.get_total_kills(); - if (m_kills >= action.kills) { - break; - } - } - use_all_ready_skill(); - } - - // 计算费用变化量 - if (action.cost_changes != 0 || action.costs) { - while (!need_exit()) { - BattleImageAnalyzer analyzer(ctrler()->get_image()); - analyzer.set_target(BattleImageAnalyzer::Target::Cost); - if (analyzer.analyze()) { - int cost = analyzer.get_cost(); - if (cost_base == -1) { - cost_base = cost; - continue; - } - if (action.cost_changes != 0) { - if ((cost_base + action.cost_changes < 0) ? (cost <= cost_base + action.cost_changes) - : (cost >= cost_base + action.cost_changes)) { - break; - } - } - if (action.costs && cost >= action.costs) { + do { + update_cost(image); + if (action.cost_changes != 0) { + if ((pre_cost + action.cost_changes < 0) ? (m_cost <= pre_cost + action.cost_changes) + : (m_cost >= pre_cost + action.cost_changes)) { break; } } - use_all_ready_skill(); + use_all_ready_skill_then_update_image(); + } while (!need_exit()); + } + + if (m_kills < action.kills) { + update_image_if_empty(); + while (!need_exit() && m_kills < action.kills) { + update_kills(image); + if (m_kills >= action.kills) { + break; + } + use_all_ready_skill_then_update_image(); + } + } + + if (action.costs) { + update_image_if_empty(); + while (!need_exit()) { + update_cost(image); + if (m_cost >= action.costs) { + break; + } + use_all_ready_skill_then_update_image(); } } // 计算有几个干员在cd if (action.cooling >= 0) { + update_image_if_empty(); while (!need_exit()) { - update_deployment(); + update_deployment(false, image); size_t cooling_count = ranges::count_if(m_cur_deployment_opers | views::values, [](const auto& oper) -> bool { return oper.cooling; }); if (cooling_count == action.cooling) { break; } - use_all_ready_skill(); + use_all_ready_skill_then_update_image(); } } // 部署干员还有额外等待费用够或 CD 转好 if (!m_in_bullet_time && action.type == ActionType::Deploy) { const std::string& name = m_oper_in_group[action.group_name]; + update_image_if_empty(); while (!need_exit()) { - update_deployment(); + update_deployment(false, image); if (auto iter = m_cur_deployment_opers.find(name); iter != m_cur_deployment_opers.cend() && iter->second.available) { break; } - use_all_ready_skill(); + use_all_ready_skill_then_update_image(); } } diff --git a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp index cf212f8b6c..7b52417ba0 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp @@ -314,7 +314,8 @@ bool asst::RoguelikeBattleTaskPlugin::do_once() { check_drone_tiles(); - if (!m_first_deploy && use_all_ready_skill()) { + cv::Mat image = ctrler()->get_image(); + if (!m_first_deploy && use_all_ready_skill(image)) { return true; } @@ -324,7 +325,7 @@ bool asst::RoguelikeBattleTaskPlugin::do_once() } auto pre_battlefield = m_battlefield_opers; - if (!update_deployment()) { + if (!update_deployment(false, image)) { return false; } diff --git a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h index ffcedae7be..5a39cd7649 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h +++ b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h @@ -108,7 +108,6 @@ namespace asst { bool wait_blocking = true; bool wait_medic = true; - bool indeed_no_medic = false; Point blocking_pos; }; std::vector m_homes_status;