mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-16 09:50:40 +08:00
feat: 支持全部主线关卡导航(仅 core 部分)
This commit is contained in:
@@ -52,6 +52,8 @@ TaskId ASSTAPI AsstAppendTask(AsstHandle handle, const char* type, const char* p
|
||||
{
|
||||
"enable": bool, // 是否启用本任务,可选,默认为 true
|
||||
"stage": string, // 关卡名,可选,默认为空,识别当前/上次的关卡。不支持运行中设置
|
||||
// 支持全部主线关卡,如 "1-7"、"S3-2"等
|
||||
// 另支持少部分资源关卡,如 "CE-6" 等(请参考 C# 集成示例)
|
||||
"medicine": int, // 最大使用理智药数量,可选,默认 0
|
||||
"stone": int, // 最大吃石头数量,可选,默认 0
|
||||
"times": int, // 指定次数,可选,默认无穷大
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
"SwipeRightToStage1-7"
|
||||
]
|
||||
},
|
||||
"EpisodeStageNameOcr": {
|
||||
"algorithm": "OcrDetect",
|
||||
"fullMatch": true,
|
||||
"text": [],
|
||||
"maxTimes": 10
|
||||
},
|
||||
"Episode10": {
|
||||
"algorithm": "JustReturn",
|
||||
"action": "DoNothing",
|
||||
|
||||
@@ -5,16 +5,18 @@
|
||||
#include "ProcessTask.h"
|
||||
#include "StageDropsTaskPlugin.h"
|
||||
#include "GameCrashRestartTaskPlugin.h"
|
||||
#include "StageNavigationTask.h"
|
||||
|
||||
asst::FightTask::FightTask(AsstCallback callback, void* callback_arg)
|
||||
: PackageTask(std::move(callback), callback_arg, TaskType),
|
||||
m_start_up_task_ptr(std::make_shared<ProcessTask>(m_callback, m_callback_arg, TaskType)),
|
||||
m_stage_task_ptr(std::make_shared<ProcessTask>(m_callback, m_callback_arg, TaskType)),
|
||||
m_last_battle_task_ptr(std::make_shared<ProcessTask>(m_callback, m_callback_arg, TaskType)),
|
||||
m_stage_navigation_task_ptr(std::make_shared<StageNavigationTask>(m_callback, m_callback_arg, TaskType)),
|
||||
m_fight_task_ptr(std::make_shared<ProcessTask>(m_callback, m_callback_arg, TaskType))
|
||||
{
|
||||
// 进入选关界面(主界面的“终端”点进去)
|
||||
m_start_up_task_ptr->
|
||||
set_times_limit("GoLastBattle", 0)
|
||||
set_times_limit("GoLastBattle", 0)
|
||||
.set_times_limit("StartButton1", 0)
|
||||
.set_times_limit("StartButton2", 0)
|
||||
.set_times_limit("MedicineConfirm", 0)
|
||||
@@ -22,14 +24,17 @@ asst::FightTask::FightTask(AsstCallback callback, void* callback_arg)
|
||||
.set_times_limit("StageSNReturnFlag", 0)
|
||||
.set_ignore_error(false);
|
||||
|
||||
// 进入对应的关卡
|
||||
m_stage_task_ptr->set_times_limit("StartButton1", 0)
|
||||
// 进入上次战斗
|
||||
m_last_battle_task_ptr->set_tasks({ "UsePrts", "UsePrts-StageSN", "StartButton1", "LastBattle" });
|
||||
m_last_battle_task_ptr->set_times_limit("StartButton1", 0)
|
||||
.set_times_limit("StartButton2", 0)
|
||||
.set_times_limit("MedicineConfirm", 0)
|
||||
.set_times_limit("StoneConfirm", 0)
|
||||
.set_times_limit("StageSNReturnFlag", 0)
|
||||
.set_ignore_error(false);
|
||||
|
||||
m_stage_navigation_task_ptr->set_enable(false);
|
||||
|
||||
// 开始战斗任务
|
||||
m_fight_task_ptr->set_tasks({ "FightBegin" })
|
||||
.set_times_limit("MedicineConfirm", 0)
|
||||
@@ -44,7 +49,8 @@ asst::FightTask::FightTask(AsstCallback callback, void* callback_arg)
|
||||
m_game_restart_plugin_ptr->set_retry_times(0);
|
||||
|
||||
m_subtasks.emplace_back(m_start_up_task_ptr);
|
||||
m_subtasks.emplace_back(m_stage_task_ptr);
|
||||
m_subtasks.emplace_back(m_last_battle_task_ptr);
|
||||
m_subtasks.emplace_back(m_stage_navigation_task_ptr);
|
||||
m_subtasks.emplace_back(m_fight_task_ptr);
|
||||
}
|
||||
|
||||
@@ -70,11 +76,14 @@ bool asst::FightTask::set_params(const json::value& params)
|
||||
if (!m_finished) {
|
||||
if (stage.empty()) {
|
||||
m_start_up_task_ptr->set_tasks({ "UsePrts", "UsePrts-StageSN", "StartButton1", "StageBegin" });
|
||||
m_stage_task_ptr->set_tasks({ "UsePrts", "UsePrts-StageSN", "StartButton1", "LastBattle" });
|
||||
m_last_battle_task_ptr->set_enable(true);
|
||||
m_stage_navigation_task_ptr->set_enable(false);
|
||||
}
|
||||
else {
|
||||
m_start_up_task_ptr->set_tasks({ "StageBegin" });
|
||||
m_stage_task_ptr->set_tasks({ stage });
|
||||
m_last_battle_task_ptr->set_enable(false);
|
||||
m_stage_navigation_task_ptr->set_stage_name(stage);
|
||||
m_stage_navigation_task_ptr->set_enable(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace asst
|
||||
class ProcessTask;
|
||||
class StageDropsTaskPlugin;
|
||||
class GameCrashRestartTaskPlugin;
|
||||
class StageNavigationTask;
|
||||
|
||||
class FightTask final : public PackageTask
|
||||
{
|
||||
@@ -21,7 +22,8 @@ namespace asst
|
||||
protected:
|
||||
|
||||
std::shared_ptr<ProcessTask> m_start_up_task_ptr = nullptr;
|
||||
std::shared_ptr<ProcessTask> m_stage_task_ptr = nullptr;
|
||||
std::shared_ptr<ProcessTask> m_last_battle_task_ptr = nullptr;
|
||||
std::shared_ptr<StageNavigationTask> m_stage_navigation_task_ptr = nullptr;
|
||||
std::shared_ptr<ProcessTask> m_fight_task_ptr = nullptr;
|
||||
std::shared_ptr<StageDropsTaskPlugin> m_stage_drops_plugin_ptr = nullptr;
|
||||
std::shared_ptr<GameCrashRestartTaskPlugin> m_game_restart_plugin_ptr = nullptr;
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<ClInclude Include="StageDropsConfiger.h" />
|
||||
<ClInclude Include="StageDropsImageAnalyzer.h" />
|
||||
<ClInclude Include="StageDropsTaskPlugin.h" />
|
||||
<ClInclude Include="StageNavigationTask.h" />
|
||||
<ClInclude Include="StartGameTaskPlugin.h" />
|
||||
<ClInclude Include="StartUpTask.h" />
|
||||
<ClInclude Include="StopGameTaskPlugin.h" />
|
||||
@@ -189,6 +190,7 @@
|
||||
<ClCompile Include="StageDropsConfiger.cpp" />
|
||||
<ClCompile Include="StageDropsImageAnalyzer.cpp" />
|
||||
<ClCompile Include="StageDropsTaskPlugin.cpp" />
|
||||
<ClCompile Include="StageNavigationTask.cpp" />
|
||||
<ClCompile Include="StartGameTaskPlugin.cpp" />
|
||||
<ClCompile Include="StartUpTask.cpp" />
|
||||
<ClCompile Include="StopGameTaskPlugin.cpp" />
|
||||
|
||||
@@ -378,6 +378,9 @@
|
||||
<ClInclude Include="NoWarningCVMat.h">
|
||||
<Filter>头文件\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StageNavigationTask.h">
|
||||
<Filter>头文件\Task\Sub</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Controller.cpp">
|
||||
@@ -644,6 +647,9 @@
|
||||
<ClCompile Include="RoguelikeResetTaskPlugin.cpp">
|
||||
<Filter>源文件\Task\Plugin\Roguelike</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StageNavigationTask.cpp">
|
||||
<Filter>源文件\Task\Sub</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\resource\config.json">
|
||||
|
||||
67
src/MeoAssistant/StageNavigationTask.cpp
Normal file
67
src/MeoAssistant/StageNavigationTask.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "StageNavigationTask.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "TaskData.h"
|
||||
#include "Controller.h"
|
||||
#include "OcrImageAnalyzer.h"
|
||||
#include "ProcessTask.h"
|
||||
#include "Logger.hpp"
|
||||
|
||||
void asst::StageNavigationTask::set_stage_name(std::string stage_name)
|
||||
{
|
||||
m_stage_name = std::move(stage_name);
|
||||
}
|
||||
|
||||
bool asst::StageNavigationTask::_run()
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
// 已有关卡优先使用 tasks.json 中的逻辑
|
||||
if (Task.get(m_stage_name)) {
|
||||
return ProcessTask(*this, { m_stage_name }).run();
|
||||
}
|
||||
|
||||
return chapter_wayfinding()
|
||||
&& swipe_and_find_stage();
|
||||
}
|
||||
|
||||
bool asst::StageNavigationTask::chapter_wayfinding()
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
static const std::regex EpisodeRegex(R"(^[A-Z]*(\d+)-\d+$)");
|
||||
std::smatch episode_sm;
|
||||
if (!std::regex_match(m_stage_name, episode_sm, EpisodeRegex)) {
|
||||
Log.error("Unkown stage", m_stage_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const std::string EpisodeTaskPrefix = "Episode";
|
||||
std::string episode_task_name = EpisodeTaskPrefix + episode_sm[1].str();
|
||||
|
||||
Log.info("capter name", episode_task_name);
|
||||
|
||||
return Task.get(episode_task_name)
|
||||
&& ProcessTask(*this, { episode_task_name }).run();
|
||||
}
|
||||
|
||||
bool asst::StageNavigationTask::swipe_and_find_stage()
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
ProcessTask(*this, { "SwipeToTheRight" }).run();
|
||||
|
||||
auto task_ptr = Task.get("EpisodeStageNameOcr");
|
||||
for (int i = 0; i < task_ptr->max_times; ++i) {
|
||||
OcrImageAnalyzer analyzer(m_ctrler->get_image());
|
||||
analyzer.set_task_info(task_ptr);
|
||||
analyzer.set_required({ m_stage_name });
|
||||
if (analyzer.analyze()) {
|
||||
m_ctrler->click(analyzer.get_result().front().rect);
|
||||
return true;
|
||||
}
|
||||
ProcessTask(*this, { "SlowlySwipeToTheLeft" }).run();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
22
src/MeoAssistant/StageNavigationTask.h
Normal file
22
src/MeoAssistant/StageNavigationTask.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "AbstractTask.h"
|
||||
|
||||
namespace asst
|
||||
{
|
||||
class StageNavigationTask : public AbstractTask
|
||||
{
|
||||
public:
|
||||
using AbstractTask::AbstractTask;
|
||||
virtual ~StageNavigationTask() noexcept override = default;
|
||||
|
||||
void set_stage_name(std::string stage_name);
|
||||
|
||||
protected:
|
||||
virtual bool _run() override;
|
||||
|
||||
bool chapter_wayfinding();
|
||||
bool swipe_and_find_stage();
|
||||
|
||||
std::string m_stage_name;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user