diff --git a/resource/tasks.json b/resource/tasks.json
index 09cd9ff3da..3141e88576 100644
--- a/resource/tasks.json
+++ b/resource/tasks.json
@@ -9604,6 +9604,11 @@
39,
250,
203
+ ],
+ "postDelay": 2000,
+ "next": [
+ "SSSStartFighting2",
+ "SSSDropRecruitmentFlag"
]
},
"SSSClickUntilStartScreen": {
diff --git a/src/MaaCore/MaaCore.vcxproj b/src/MaaCore/MaaCore.vcxproj
index 39614d24a6..2341b7da6e 100644
--- a/src/MaaCore/MaaCore.vcxproj
+++ b/src/MaaCore/MaaCore.vcxproj
@@ -35,6 +35,7 @@
+
@@ -157,6 +158,7 @@
+
@@ -404,7 +406,7 @@
-
+
\ No newline at end of file
diff --git a/src/MaaCore/MaaCore.vcxproj.filters b/src/MaaCore/MaaCore.vcxproj.filters
index 9e7d4094eb..204e7705d4 100644
--- a/src/MaaCore/MaaCore.vcxproj.filters
+++ b/src/MaaCore/MaaCore.vcxproj.filters
@@ -465,9 +465,6 @@
源文件\Task\Interface
-
- 源文件\Task\Roguelike
-
源文件\Config\Miscellaneous
@@ -477,6 +474,12 @@
源文件\Task\SSS
+
+ 源文件\Task\SSS
+
+
+ 源文件\Task\Miscellaneous
+
@@ -782,5 +785,8 @@
源文件\Task\SSS
+
+ 源文件\Task\SSS
+
\ No newline at end of file
diff --git a/src/MaaCore/Task/Interface/SSSCopilotTask.cpp b/src/MaaCore/Task/Interface/SSSCopilotTask.cpp
index d39aa34e5a..705f11360b 100644
--- a/src/MaaCore/Task/Interface/SSSCopilotTask.cpp
+++ b/src/MaaCore/Task/Interface/SSSCopilotTask.cpp
@@ -4,6 +4,7 @@
#include "Config/TaskData.h"
#include "Task/Miscellaneous/BattleFormationTask.h"
#include "Task/ProcessTask.h"
+#include "Task/SSS/SSSDropRewardsTaskPlugin.h"
#include "Task/SSS/SSSStageManagerTask.h"
#include "Utils/Logger.hpp"
#include "Utils/Platform.hpp"
@@ -28,6 +29,7 @@ asst::SSSCopilotTask::SSSCopilotTask(const AsstCallback& callback, Assistant* in
.set_ignore_error(false);
m_subtasks.emplace_back(start_2_tp);
+ m_stage_task_ptr->register_plugin();
m_subtasks.emplace_back(m_stage_task_ptr);
}
diff --git a/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp b/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp
new file mode 100644
index 0000000000..7846cbb54f
--- /dev/null
+++ b/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.cpp
@@ -0,0 +1,60 @@
+#include "SSSDropRewardsTaskPlugin.h"
+
+#include "Config/Miscellaneous/BattleDataConfig.h"
+#include "Config/Miscellaneous/SSSCopilotConfig.h"
+#include "Controller.h"
+#include "Task/ProcessTask.h"
+#include "Task/SSS/SSSBattleProcessTask.h"
+#include "Utils/Logger.hpp"
+#include "Vision/OcrImageAnalyzer.h"
+#include "Vision/OcrWithPreprocessImageAnalyzer.h"
+
+bool asst::SSSDropRewardsTaskPlugin::verify(AsstMsg msg, const json::value& details) const
+{
+ if (msg != AsstMsg::SubTaskStart || details.get("subtask", std::string()) != "ProcessTask") {
+ return false;
+ }
+
+ const std::string& task = details.get("details", "task", "");
+ return task == "SSSDropRecruitmentFlag";
+}
+
+bool asst::SSSDropRewardsTaskPlugin::_run()
+{
+ using namespace battle;
+ LogTraceFunction;
+
+ OcrImageAnalyzer analyzer(ctrler()->get_image());
+ analyzer.set_task_info("SSSDropRecruitmentOCR");
+ if (!analyzer.analyze()) {
+ Log.error(__FUNCTION__, "OCR failed to analyze");
+ return false;
+ }
+
+ struct DropRecruitment
+ {
+ TextRect ocr_res;
+ std::optional role;
+ };
+
+ std::vector opers;
+ for (const auto& result : analyzer.get_result()) {
+ auto role = BattleData.get_role(result.text);
+ opers.emplace_back(DropRecruitment {
+ .ocr_res = result, .role = role == Role::Unknown ? std::nullopt : std::optional(role) });
+ }
+
+ for (const std::string& name : SSSCopilot.get_data().drop_tool_men) {
+ auto role = get_role_type(name);
+ bool is_role = role != Role::Unknown;
+ auto iter = ranges::find_if(opers, [&](const DropRecruitment& props) {
+ return (is_role && props.role) ? *props.role == role : props.ocr_res.text == name;
+ });
+ if (iter != opers.cend()) {
+ ctrler()->click(iter->ocr_res.rect);
+ break;
+ }
+ }
+
+ return ProcessTask(*this, { "SSSDropRecruitmentConfrim" }).run();
+}
diff --git a/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.h b/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.h
new file mode 100644
index 0000000000..1261dc7a8a
--- /dev/null
+++ b/src/MaaCore/Task/SSS/SSSDropRewardsTaskPlugin.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "Task/AbstractTaskPlugin.h"
+
+namespace asst
+{
+ class SSSDropRewardsTaskPlugin : public AbstractTaskPlugin
+ {
+ public:
+ using AbstractTaskPlugin::AbstractTaskPlugin;
+ virtual ~SSSDropRewardsTaskPlugin() noexcept override = default;
+
+ virtual bool verify(AsstMsg msg, const json::value& details) const override;
+
+ protected:
+ bool _run() override;
+ };
+}
diff --git a/src/MaaCore/Task/SSS/SSSStageManagerTask.cpp b/src/MaaCore/Task/SSS/SSSStageManagerTask.cpp
index 735142a53e..84ba3123e3 100644
--- a/src/MaaCore/Task/SSS/SSSStageManagerTask.cpp
+++ b/src/MaaCore/Task/SSS/SSSStageManagerTask.cpp
@@ -73,61 +73,13 @@ std::optional asst::SSSStageManagerTask::analyze_stage()
bool asst::SSSStageManagerTask::comfirm_battle_complete()
{
- ProcessTask task(*this, { "SSSComfirmBattleComplete" });
- task.set_times_limit("SSSStartFighting", 0).set_times_limit("SSSBegin", 0);
- if (!task.run()) {
- return false;
- }
-
- if (const std::string& last = task.get_last_task_name(); last == "SSSStartFighting") {
- return true;
- }
- else if (last == "SSSDropRecruitmentFlag") {
- get_drop_rewards();
- return false;
- }
- return false;
+ return ProcessTask(*this, { "SSSComfirmBattleComplete" })
+ .set_times_limit("SSSStartFighting", 0)
+ .set_times_limit("SSSBegin", 0)
+ .run();
}
-bool asst::SSSStageManagerTask::get_drop_rewards()
-{
- using namespace battle;
- LogTraceFunction;
-
- OcrImageAnalyzer analyzer(ctrler()->get_image());
- analyzer.set_task_info("SSSDropRecruitmentOCR");
- if (!analyzer.analyze()) {
- Log.error(__FUNCTION__, "OCR failed to analyze");
- return false;
- }
-
- struct DropRecruitment
- {
- TextRect ocr_res;
- std::optional role;
- };
-
- std::vector opers;
- for (const auto& result : analyzer.get_result()) {
- auto role = BattleData.get_role(result.text);
- opers.emplace_back(DropRecruitment {
- .ocr_res = result, .role = role == Role::Unknown ? std::nullopt : std::optional(role) });
- }
-
- for (const std::string& name : SSSCopilot.get_data().drop_tool_men) {
- auto role = get_role_type(name);
- bool is_role = role != Role::Unknown;
- auto iter = ranges::find_if(opers, [&](const DropRecruitment& props) {
- return (is_role && props.role) ? *props.role == role : props.ocr_res.text == name;
- });
- if (iter != opers.cend()) {
- ctrler()->click(iter->ocr_res.rect);
- break;
- }
- }
-
- return ProcessTask(*this, { "SSSDropRecruitmentConfrim" }).run();
-}
+bool asst::SSSStageManagerTask::get_drop_rewards() {}
bool asst::SSSStageManagerTask::click_start_button()
{