mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-16 01:40:46 +08:00
feat: 新增沙盘推演作业支持 (#16578)
新增沙盘推演相关配置字段与识别逻辑,添加沙盘选项弹窗、确认等任务配置,支持设置两个沙盘选项参数,适配单多编队作业的沙盘模式调用
This commit is contained in:
@@ -389,6 +389,59 @@
|
||||
"template": ["RaidDifficulty.png", "RaidDifficulty-Chapter15.png"],
|
||||
"next": []
|
||||
},
|
||||
"SandboxOptionToggle": {
|
||||
"doc": "沙盘推演选项弹窗按钮",
|
||||
"template": "SandboxOptionToggle.png",
|
||||
"action": "ClickSelf",
|
||||
"roi": [1131, 123, 149, 148],
|
||||
"preDelay": 500,
|
||||
"next": []
|
||||
},
|
||||
"SandboxButton": {
|
||||
"doc": "沙盘推演按钮",
|
||||
"algorithm": "OcrDetect",
|
||||
"action": "ClickSelf",
|
||||
"text": ["沙盘推演"],
|
||||
"roi": [910, 128, 244, 138],
|
||||
"maxTimes": 3,
|
||||
"next": ["SandboxOptionToggle", "#self"]
|
||||
},
|
||||
"SandboxOption1_1": {
|
||||
"doc": "沙盘选项1-1",
|
||||
"algorithm": "JustReturn",
|
||||
"action": "ClickRect",
|
||||
"specificRect": [63, 263, 574, 128],
|
||||
"preDelay": 1000
|
||||
},
|
||||
"SandboxOption1_2": {
|
||||
"doc": "沙盘选项1-2",
|
||||
"algorithm": "JustReturn",
|
||||
"action": "ClickRect",
|
||||
"specificRect": [643, 264, 580, 132],
|
||||
"preDelay": 1000
|
||||
},
|
||||
"SandboxOption2_1": {
|
||||
"doc": "沙盘选项2-1",
|
||||
"algorithm": "JustReturn",
|
||||
"action": "ClickRect",
|
||||
"specificRect": [58, 463, 582, 130],
|
||||
"preDelay": 500
|
||||
},
|
||||
"SandboxOption2_2": {
|
||||
"doc": "沙盘选项2-2",
|
||||
"algorithm": "JustReturn",
|
||||
"action": "ClickRect",
|
||||
"specificRect": [641, 466, 580, 126],
|
||||
"preDelay": 500
|
||||
},
|
||||
"SandboxConfirm": {
|
||||
"doc": "沙盘推演确定按钮",
|
||||
"algorithm": "OcrDetect",
|
||||
"action": "ClickSelf",
|
||||
"text": ["确定"],
|
||||
"roi": [939, 570, 333, 150],
|
||||
"preDelay": 500
|
||||
},
|
||||
"EpisodeNew": {
|
||||
"Doc": "base_task",
|
||||
"algorithm": "JustReturn",
|
||||
|
||||
BIN
resource/template/SandboxOptionToggle.png
Normal file
BIN
resource/template/SandboxOptionToggle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
@@ -441,6 +441,9 @@ struct BasicInfo
|
||||
std::string title_color;
|
||||
std::string details;
|
||||
std::string details_color;
|
||||
bool is_sandbox = false;
|
||||
int sandbox_option1 = 1;
|
||||
int sandbox_option2 = 1;
|
||||
};
|
||||
|
||||
struct CombatData // 作业 JSON 数据
|
||||
|
||||
@@ -40,6 +40,10 @@ asst::battle::copilot::BasicInfo asst::CopilotConfig::parse_basic_info(const jso
|
||||
info.details = json.get("doc", "details", std::string());
|
||||
info.details_color = json.get("doc", "details_color", std::string());
|
||||
|
||||
info.is_sandbox = json.get("is_sandbox", false);
|
||||
info.sandbox_option1 = json.get("sandbox_option1", 1);
|
||||
info.sandbox_option2 = json.get("sandbox_option2", 1);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "CopilotTask.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Arknights-Tile-Pos/TileCalc2.hpp"
|
||||
|
||||
#include "Config/Miscellaneous/BattleDataConfig.h"
|
||||
@@ -90,13 +92,37 @@ bool asst::CopilotTask::set_params(const json::value& params)
|
||||
Log.error("Not support stage");
|
||||
return false;
|
||||
}
|
||||
if (Copilot.get_data().info.is_sandbox) {
|
||||
int opt1 = std::clamp(Copilot.get_data().info.sandbox_option1, 1, 2);
|
||||
int opt2 = std::clamp(Copilot.get_data().info.sandbox_option2, 1, 2);
|
||||
m_sandbox_tasks.clear();
|
||||
auto raid_tp = std::make_shared<ProcessTask>(m_callback, inst(), TaskType);
|
||||
raid_tp->set_tasks({ "RaidConfirm", "ChangeToRaidDifficulty" }).set_retry_times(20);
|
||||
m_sandbox_tasks.emplace_back(raid_tp);
|
||||
auto sandbox_entry_tp = std::make_shared<ProcessTask>(m_callback, inst(), TaskType);
|
||||
sandbox_entry_tp->set_tasks({ "SandboxOptionToggle", "SandboxButton" }).set_retry_times(20);
|
||||
m_sandbox_tasks.emplace_back(sandbox_entry_tp);
|
||||
std::vector<std::string> sandbox_steps = { "SandboxOption1_" + std::to_string(opt1),
|
||||
"SandboxOption2_" + std::to_string(opt2),
|
||||
"SandboxConfirm" };
|
||||
for (const auto& task_name : sandbox_steps) {
|
||||
auto tp = std::make_shared<ProcessTask>(m_callback, inst(), TaskType);
|
||||
tp->set_tasks({ task_name }).set_retry_times(20);
|
||||
m_sandbox_tasks.emplace_back(tp);
|
||||
}
|
||||
size_t insert_pos = 1;
|
||||
for (const auto& tp : m_sandbox_tasks) {
|
||||
m_subtasks.insert(m_subtasks.begin() + insert_pos, tp);
|
||||
++insert_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (multi_tasks_opt) {
|
||||
m_multi_copilot_plugin_ptr->set_enable(true); // 启用多任务插件, 自动覆盖Copilot中的配置
|
||||
m_battle_task_ptr->set_wait_until_end(true);
|
||||
auto configs = static_cast<std::vector<MultiCopilotConfig>>(*multi_tasks_opt);
|
||||
std::vector<MultiCopilotTaskPlugin::MultiCopilotConfig> configs_cvt;
|
||||
for (const auto& [id, filename, stage_name, is_raid] : configs) {
|
||||
for (const auto& [id, filename, stage_name, is_raid, is_sandbox, sandbox_option1, sandbox_option2] : configs) {
|
||||
MultiCopilotTaskPlugin::MultiCopilotConfig config_cvt;
|
||||
auto copilot_opt = parse_copilot_filename(filename);
|
||||
if (!copilot_opt) {
|
||||
@@ -110,6 +136,9 @@ bool asst::CopilotTask::set_params(const json::value& params)
|
||||
config_cvt.nav_name = stage_name;
|
||||
config_cvt.is_raid = is_raid;
|
||||
config_cvt.id = id; // ID 从0开始
|
||||
config_cvt.is_sandbox = is_sandbox;
|
||||
config_cvt.sandbox_option1 = sandbox_option1;
|
||||
config_cvt.sandbox_option2 = sandbox_option2;
|
||||
configs_cvt.emplace_back(std::move(config_cvt));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,21 @@ public:
|
||||
struct MultiCopilotConfig
|
||||
{
|
||||
int id = -1;
|
||||
std::string filename; // 文件名
|
||||
std::string stage_name; // 关卡名
|
||||
bool is_raid = false; // 是否是突袭
|
||||
std::string filename; // 文件名
|
||||
std::string stage_name; // 关卡名
|
||||
bool is_raid = false; // 是否是突袭
|
||||
bool is_sandbox = false; // 是否是沙盘推演
|
||||
int sandbox_option1 = 1; // 沙盘选项1 (1 or 2)
|
||||
int sandbox_option2 = 1; // 沙盘选项2 (1 or 2)
|
||||
|
||||
MEO_JSONIZATION(MEO_OPT id, filename, stage_name, MEO_OPT is_raid);
|
||||
MEO_JSONIZATION(
|
||||
MEO_OPT id,
|
||||
filename,
|
||||
stage_name,
|
||||
MEO_OPT is_raid,
|
||||
MEO_OPT is_sandbox,
|
||||
MEO_OPT sandbox_option1,
|
||||
MEO_OPT sandbox_option2);
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -40,6 +50,7 @@ private:
|
||||
std::optional<std::filesystem::path> parse_copilot_filename(const std::string& name);
|
||||
|
||||
std::shared_ptr<MultiCopilotTaskPlugin> m_multi_copilot_plugin_ptr = nullptr;
|
||||
std::vector<std::shared_ptr<ProcessTask>> m_sandbox_tasks;
|
||||
std::shared_ptr<ProcessTask> m_medicine_task_ptr = nullptr;
|
||||
std::shared_ptr<BattleFormationTask> m_formation_task_ptr = nullptr;
|
||||
std::shared_ptr<BattleProcessTask> m_battle_task_ptr = nullptr;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "MultiCopilotTaskPlugin.h"
|
||||
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Config/GeneralConfig.h"
|
||||
#include "Config/Miscellaneous/CopilotConfig.h"
|
||||
@@ -47,10 +48,24 @@ bool asst::MultiCopilotTaskPlugin::_run()
|
||||
ret = ret && navigate_to_stage(config.nav_name);
|
||||
|
||||
ProcessTask(*this, { "NotUsePrts" }).set_ignore_error(true).set_retry_times(0).run();
|
||||
if (config.is_raid) {
|
||||
// 选择突袭模式
|
||||
|
||||
bool is_sandbox = config.is_sandbox || Copilot.get_data().info.is_sandbox;
|
||||
int sandbox_option1 =
|
||||
std::clamp(config.is_sandbox ? config.sandbox_option1 : Copilot.get_data().info.sandbox_option1, 1, 2);
|
||||
int sandbox_option2 =
|
||||
std::clamp(config.is_sandbox ? config.sandbox_option2 : Copilot.get_data().info.sandbox_option2, 1, 2);
|
||||
|
||||
if (config.is_raid || is_sandbox) {
|
||||
ret = ret && ProcessTask(*this, { "RaidConfirm", "ChangeToRaidDifficulty" }).set_retry_times(20).run();
|
||||
}
|
||||
if (ret && is_sandbox) {
|
||||
ret = ret && ProcessTask(*this, { "SandboxOptionToggle", "SandboxButton" }).set_retry_times(20).run();
|
||||
std::string option1_task = "SandboxOption1_" + std::to_string(sandbox_option1);
|
||||
ret = ret && ProcessTask(*this, { option1_task }).set_retry_times(3).run();
|
||||
std::string option2_task = "SandboxOption2_" + std::to_string(sandbox_option2);
|
||||
ret = ret && ProcessTask(*this, { option2_task }).set_retry_times(3).run();
|
||||
ret = ret && ProcessTask(*this, { "SandboxConfirm" }).set_retry_times(20).run();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ public:
|
||||
std::string nav_name; // 关卡名
|
||||
bool is_raid = false; // 是否是突袭
|
||||
int id;
|
||||
bool is_sandbox = false; // 是否是沙盘推演
|
||||
int sandbox_option1 = 1; // 沙盘选项1 (1 or 2)
|
||||
int sandbox_option2 = 1; // 沙盘选项2 (1 or 2)
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -47,6 +47,12 @@ public class CopilotModel : CopilotBase
|
||||
[JsonProperty("difficulty")]
|
||||
public DifficultyFlags Difficulty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether 沙盘推演模式
|
||||
/// </summary>
|
||||
[JsonProperty("is_sandbox")]
|
||||
public bool IsSandbox { get; set; }
|
||||
|
||||
public List<(string Output, string? Color)> Output()
|
||||
{
|
||||
var output = new List<(string, string?)>();
|
||||
|
||||
@@ -1721,13 +1721,13 @@ public partial class CopilotViewModel : Screen
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags.HasFlag(CopilotModel.DifficultyFlags.Normal))
|
||||
if (flags.HasFlag(CopilotModel.DifficultyFlags.Normal) && !copilot.IsSandbox)
|
||||
{
|
||||
var item = new CopilotItemViewModel(stageCode, cachePath, false, copilotId) { Index = CopilotItemViewModels.Count, };
|
||||
CopilotItemViewModels.Add(item);
|
||||
}
|
||||
|
||||
if (flags.HasFlag(CopilotModel.DifficultyFlags.Raid))
|
||||
if (flags.HasFlag(CopilotModel.DifficultyFlags.Raid) || copilot.IsSandbox)
|
||||
{
|
||||
var item = new CopilotItemViewModel(stageCode, cachePath, true, copilotId) { Index = CopilotItemViewModels.Count, };
|
||||
CopilotItemViewModels.Add(item);
|
||||
|
||||
Reference in New Issue
Block a user