diff --git a/MAA.sln.DotSettings b/MAA.sln.DotSettings
index 6aa01a9b05..784fa2b25f 100644
--- a/MAA.sln.DotSettings
+++ b/MAA.sln.DotSettings
@@ -41,6 +41,7 @@
True
True
True
+ True
True
True
True
@@ -51,6 +52,7 @@
True
True
True
+ True
True
True
True
diff --git a/resource/config.json b/resource/config.json
index 6d2cc61874..fd12efaec7 100644
--- a/resource/config.json
+++ b/resource/config.json
@@ -3,6 +3,12 @@
"options": {
"taskDelay": 500,
"taskDelay_Doc": "识别的延迟:越快识别频率越快,但会增加CPU消耗。单位毫秒,默认500",
+ "SSSFightScreencapInterval": 0,
+ "SSSFightScreencapInterval_Doc": "保全战斗截图最小间隔",
+ "RoguelikeFightScreencapInterval": 100,
+ "RoguelikeFightScreencapInterval_Doc": "肉鸽战斗截图最小间隔",
+ "CopilotFightScreencapInterval": 0,
+ "CopilotFightScreencapInterval_Doc": "抄作业战斗截图最小间隔",
"controlDelayRange": [
0,
0
diff --git a/src/MaaCore/Config/GeneralConfig.cpp b/src/MaaCore/Config/GeneralConfig.cpp
index 5e3e01e865..51b0e57fdd 100644
--- a/src/MaaCore/Config/GeneralConfig.cpp
+++ b/src/MaaCore/Config/GeneralConfig.cpp
@@ -19,6 +19,9 @@ bool asst::GeneralConfig::parse(const json::value& json)
{
const json::value& options_json = json.at("options");
m_options.task_delay = options_json.at("taskDelay").as_integer();
+ m_options.sss_fight_screencap_interval = options_json.at("SSSFightScreencapInterval").as_integer();
+ m_options.roguelike_fight_screencap_interval = options_json.at("RoguelikeFightScreencapInterval").as_integer();
+ m_options.copilot_fight_screencap_interval = options_json.at("CopilotFightScreencapInterval").as_integer();
m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer();
m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer();
// m_options.print_window = options_json.at("printWindow").as_boolean();
diff --git a/src/MaaCore/Config/GeneralConfig.h b/src/MaaCore/Config/GeneralConfig.h
index cf0fef6dd4..9101a26d69 100644
--- a/src/MaaCore/Config/GeneralConfig.h
+++ b/src/MaaCore/Config/GeneralConfig.h
@@ -34,6 +34,9 @@ struct DebugConf
struct Options
{
int task_delay = 0; // 任务间延时:越快操作越快,但会增加CPU消耗
+ int sss_fight_screencap_interval = 0; // 保全战斗截图最小间隔
+ int roguelike_fight_screencap_interval = 0; // 肉鸽战斗截图最小间隔
+ int copilot_fight_screencap_interval = 0; // 抄作业战斗截图最小间隔
int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时
int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时
// bool print_window = false;// 截图功能:开启后每次结算界面会截图到screenshot目录下
diff --git a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp
index a40ea28250..3f6a77e950 100644
--- a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp
+++ b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp
@@ -167,9 +167,22 @@ bool asst::BattleProcessTask::do_action(const battle::copilot::Action& action, s
notify_action(action);
+ thread_local auto prev_frame_time = std::chrono::steady_clock::time_point {};
+ static constexpr auto min_frame_interval = std::chrono::milliseconds(Config.get_options().copilot_fight_screencap_interval);
+
+ // prevent our program from consuming too much CPU
+ if (const auto now = std::chrono::steady_clock::now();
+ prev_frame_time > now - min_frame_interval) [[unlikely]] {
+ Log.debug("Sleeping for framerate limit");
+ std::this_thread::sleep_for(min_frame_interval - (now - prev_frame_time));
+ }
+
if (!wait_condition(action)) {
return false;
}
+
+ prev_frame_time = std::chrono::steady_clock::now();
+
if (action.pre_delay > 0) {
sleep_and_do_strategy(action.pre_delay);
// 等待之后画面可能会变化,更新下干员信息
diff --git a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp
index f4eaa30749..040f45fe64 100644
--- a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp
+++ b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp
@@ -454,8 +454,8 @@ bool asst::RoguelikeBattleTaskPlugin::do_once()
check_drone_tiles();
// TODO: move this to controller
- static thread_local auto prev_frame_time = std::chrono::steady_clock::time_point {};
- static constexpr auto min_frame_interval = std::chrono::milliseconds(100);
+ thread_local auto prev_frame_time = std::chrono::steady_clock::time_point {};
+ static constexpr auto min_frame_interval = std::chrono::milliseconds(Config.get_options().roguelike_fight_screencap_interval);
// prevent our program from consuming too much CPU
if (const auto now = std::chrono::steady_clock::now();
diff --git a/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp b/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp
index 76df0fa311..08b6aa665e 100644
--- a/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp
+++ b/src/MaaCore/Task/SSS/SSSBattleProcessTask.cpp
@@ -94,7 +94,19 @@ bool asst::SSSBattleProcessTask::do_derived_action(const battle::copilot::Action
bool asst::SSSBattleProcessTask::do_strategic_action(const cv::Mat& reusable)
{
LogTraceFunction;
+
+ thread_local auto prev_frame_time = std::chrono::steady_clock::time_point {};
+ static constexpr auto min_frame_interval = std::chrono::milliseconds(Config.get_options().sss_fight_screencap_interval);
+
+ // prevent our program from consuming too much CPU
+ if (const auto now = std::chrono::steady_clock::now();
+ prev_frame_time > now - min_frame_interval) [[unlikely]] {
+ Log.debug("Sleeping for framerate limit");
+ std::this_thread::sleep_for(min_frame_interval - (now - prev_frame_time));
+ }
+
cv::Mat image = reusable.empty() ? ctrler()->get_image() : reusable;
+ prev_frame_time = std::chrono::steady_clock::now();
if (check_and_get_drops(image)) {
return true;