diff --git a/src/MaaCore/Common/AsstBattleDef.h b/src/MaaCore/Common/AsstBattleDef.h index e10939ff71..902bcda85e 100644 --- a/src/MaaCore/Common/AsstBattleDef.h +++ b/src/MaaCore/Common/AsstBattleDef.h @@ -233,14 +233,24 @@ namespace asst::battle RoleCounts tool_men; Point location; DeployDirection direction = DeployDirection::None; + // 以下为非json解析字段 + int index; + bool core_deployed = false; // 全局保core,再次识别到core则同location全部重置 + bool operator==(const Strategy& other) const + { + return index == other.index; + } }; + using StrategyOrderLock = std::unordered_map>, Point::Hash>; + struct CombatData : public copilot::CombatData { std::vector strategies; bool draw_as_possible = false; int retry_times = 0; std::vector order_of_drops; + StrategyOrderLock order; }; enum class EquipmentType diff --git a/src/MaaCore/Common/AsstTypes.h b/src/MaaCore/Common/AsstTypes.h index fa42039547..10810dc04e 100644 --- a/src/MaaCore/Common/AsstTypes.h +++ b/src/MaaCore/Common/AsstTypes.h @@ -75,7 +75,6 @@ namespace asst Point& operator=(const Point&) noexcept = default; Point& operator=(Point&&) noexcept = default; Point operator-() const noexcept { return { -x, -y }; } - bool operator==(const Point& rhs) const noexcept { return x == rhs.x && y == rhs.y; } std::string to_string() const { return "(" + std::to_string(x) + ", " + std::to_string(y) + ")"; } explicit operator std::string() const { return to_string(); } static constexpr Point right() { return { 1, 0 }; } @@ -86,10 +85,21 @@ namespace asst bool empty() const noexcept { return x == 0 && y == 0; } // for std::map bool operator<(const Point& rhs) const noexcept { return x < rhs.x || (x == rhs.x && y < rhs.y); } + bool operator==(const Point& rhs) const noexcept { return x == rhs.x && y == rhs.y; } int x = 0; int y = 0; + struct Hash + { + size_t operator()(const Point& p) const noexcept + { + auto h1 = std::hash {}(p.x); + auto h2 = std::hash {}(p.y); + return h1 ^ (h2 << 1); // Combine hash values + } + }; + // clang-format off #define DEFINE_ASST_POINT_BINARY_OP_AND_ARG_ASSIGN(Op) \ friend Point operator Op(const Point& lhs, const Point& rhs) noexcept \ diff --git a/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp b/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp index a80bd3a4c0..ab11d10f08 100644 --- a/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp +++ b/src/MaaCore/Config/Miscellaneous/SSSCopilotConfig.cpp @@ -66,6 +66,7 @@ bool asst::SSSCopilotConfig::parse(const json::value& json) stage_data.order_of_drops = m_data.order_of_drops; stage_data.retry_times = stage.get("retry_times", 0); + int index = 0; for (const auto& strategy_info : stage.at("strategies").as_array()) { Strategy strategy; strategy.core = strategy_info.get("core", std::string()); @@ -73,6 +74,16 @@ bool asst::SSSCopilotConfig::parse(const json::value& json) strategy.location.x = strategy_info.at("location").at(0).as_integer(); strategy.location.y = strategy_info.at("location").at(1).as_integer(); strategy.direction = CopilotConfig::string_to_direction(strategy_info.get("direction", "Right")); + // 步骤(strategy)间锁,以部署位置为key,保证core不被顶替 + strategy.index = index; + if (auto it = stage_data.order.find(strategy.location); it != stage_data.order.cend()) { + it->second.emplace_back(std::make_shared(strategy)); + } + else { + std::vector> strategy_list { std::make_shared(strategy) }; + stage_data.order.emplace(strategy.location, strategy_list); + } + index++; stage_data.strategies.emplace_back(std::move(strategy)); } std::string ocr_code; diff --git a/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp b/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp index dc9285aa16..7fd8492e3d 100644 --- a/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp +++ b/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp @@ -198,6 +198,12 @@ bool asst::SSSBattleProcessTask::check_and_do_strategy(const cv::Mat& reusable) } for (auto& strategy : m_sss_combat_data.strategies) { + // 步骤(strategy)间锁,以部署位置为key,保证core不被顶替 + auto it = m_sss_combat_data.order.find(strategy.location); + if (*(it->second.front()) != strategy) { + continue; + } + bool use_the_core = ranges::all_of(strategy.tool_men, [](const auto& pair) { return pair.second <= 0; }) && !strategy.core.empty() && exist_core.contains(strategy.core); if (use_the_core) { @@ -224,6 +230,15 @@ bool asst::SSSBattleProcessTask::check_and_do_strategy(const cv::Mat& reusable) tool_men, [&](const DeploymentOper& oper) { return oper.available && oper.role == role_for_lambda; }); if (available_iter != tool_men.cend()) { --quantity; + // 每个tool_men用尽之后删除m_sss_combat_data.strategies中tool_men的当前元素 + // 重新执行该location所有策略时用m_sss_combat_data.order进行恢复 + if (quantity <= 0) { + strategy.tool_men.erase(role); + if (strategy.tool_men.empty() && strategy.core.empty()) { + (it->second).emplace_back((it->second).front()); + (it->second).erase((it->second).begin()); + } + } // 部署完,画面会发生变化,所以直接返回,后续逻辑交给下次循环处理 return deploy_oper(available_iter->name, strategy.location, strategy.direction) && update_deployment(); }