mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-18 18:20:39 +08:00
perf: 优化肉鸽投资操作速度
This commit is contained in:
@@ -12727,24 +12727,62 @@
|
||||
]
|
||||
},
|
||||
"Roguelike@StageTraderInvestConfirm": {
|
||||
"action": "ClickSelf",
|
||||
"doc": "绑定 RoguelikeInvestTaskPlugin 插件进行投资,本任务仅作为进入投资系统时的初始化确认",
|
||||
"roi": [
|
||||
852,
|
||||
422,
|
||||
278,
|
||||
144
|
||||
],
|
||||
"postDelay": 500,
|
||||
"exceededNext": [
|
||||
"RoguelikeControlTaskPlugin-ExitThenStop"
|
||||
],
|
||||
"next": [
|
||||
"Roguelike@StageTraderInvestSystemError",
|
||||
"Roguelike@StageTraderInvestSystemFull",
|
||||
"Roguelike@StageTraderInvestConfirm",
|
||||
"Roguelike@StageTraderInvestCancel"
|
||||
]
|
||||
},
|
||||
"Roguelike@StageTraderInvest-Arrow": {
|
||||
"doc": "商店投资界面的箭头,99 >> 100",
|
||||
"roi": [
|
||||
750,
|
||||
320,
|
||||
100,
|
||||
100
|
||||
]
|
||||
},
|
||||
"Roguelike@StageTraderInvest-Confirm": {
|
||||
"algorithm": "JustReturn",
|
||||
"action": "ClickRect",
|
||||
"specificRect": [
|
||||
850,
|
||||
470,
|
||||
300,
|
||||
45
|
||||
]
|
||||
},
|
||||
"Roguelike@StageTraderInvest-Count": {
|
||||
"doc": "商店投资界面的余额显示,99 >> 100",
|
||||
"algorithm": "OcrDetect",
|
||||
"isAscii": true,
|
||||
"roi": [
|
||||
570,
|
||||
335,
|
||||
150,
|
||||
60
|
||||
]
|
||||
},
|
||||
"Roguelike@StageTraderInvest-Count-Error": {
|
||||
"doc": "商店投资界面系统出错时余额显示",
|
||||
"algorithm": "OcrDetect",
|
||||
"isAscii": true,
|
||||
"roi": [
|
||||
635,
|
||||
205,
|
||||
70,
|
||||
40
|
||||
]
|
||||
},
|
||||
"Roguelike@StageTraderInvestSystem": {
|
||||
"templThreshold": 0.75,
|
||||
"action": "ClickSelf",
|
||||
|
||||
BIN
resource/template/Roguelike@StageTraderInvest-Arrow.png
Normal file
BIN
resource/template/Roguelike@StageTraderInvest-Arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
@@ -96,6 +96,7 @@
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeFoldartalUseTaskPlugin.h" />
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeConfig.h" />
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeDifficultySelectionTaskPlugin.h" />
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeInvestTaskPlugin.h" />
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeLastRewardTaskPlugin.h" />
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeSettlementTaskPlugin.h" />
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeStrategyChangeTaskPlugin.h" />
|
||||
@@ -273,6 +274,7 @@
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeFoldartalUseTaskPlugin.cpp" />
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeConfig.cpp" />
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeDifficultySelectionTaskPlugin.cpp" />
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeInvestTaskPlugin.cpp" />
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeLastRewardTaskPlugin.cpp" />
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeSettlementTaskPlugin.cpp" />
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeStrategyChangeTaskPlugin.cpp" />
|
||||
|
||||
@@ -693,6 +693,9 @@
|
||||
<ClInclude Include="Config\TaskData\TaskDataTypes.h">
|
||||
<Filter>Source\Resource\TaskData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeInvestTaskPlugin.h">
|
||||
<Filter>Source\Task\Roguelike</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vision\VisionHelper.cpp">
|
||||
@@ -1154,5 +1157,8 @@
|
||||
<ClCompile Include="Task\Infrast\InfrastTrainingTask.cpp">
|
||||
<Filter>Source\Task\Infrast</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeInvestTaskPlugin.cpp">
|
||||
<Filter>Source\Task\Roguelike</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "Task/Roguelike/RoguelikeSkillSelectionTaskPlugin.h"
|
||||
#include "Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h"
|
||||
#include "Task/Roguelike/RoguelikeStrategyChangeTaskPlugin.h"
|
||||
#include "Task/Roguelike/RoguelikeInvestTaskPlugin.h"
|
||||
|
||||
#include "Utils/Logger.hpp"
|
||||
|
||||
@@ -40,6 +41,7 @@ asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, Assistant* inst
|
||||
m_roguelike_task_ptr->register_plugin<RoguelikeSettlementTaskPlugin>(m_roguelike_config_ptr);
|
||||
m_debug_plugin_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeDebugTaskPlugin>(m_roguelike_config_ptr);
|
||||
m_roguelike_task_ptr->register_plugin<RoguelikeShoppingTaskPlugin>(m_roguelike_config_ptr)->set_retry_times(0);
|
||||
m_roguelike_task_ptr->register_plugin<RoguelikeInvestTaskPlugin>(m_roguelike_config_ptr);
|
||||
|
||||
m_custom_start_plugin_ptr =
|
||||
m_roguelike_task_ptr->register_plugin<RoguelikeCustomStartTaskPlugin>(m_roguelike_config_ptr);
|
||||
@@ -96,6 +98,8 @@ bool asst::RoguelikeTask::set_params(const json::value& params)
|
||||
// 是否凹指定干员开局直升
|
||||
m_roguelike_config_ptr->set_start_with_elite_two(params.get("start_with_elite_two", false));
|
||||
m_roguelike_config_ptr->set_only_start_with_elite_two(params.get("only_start_with_elite_two", false));
|
||||
m_roguelike_config_ptr->set_invest_maximum(params.get("investments_count", INT_MAX));
|
||||
m_roguelike_config_ptr->set_invest_stop_when_full(params.get("stop_when_investment_full", false));
|
||||
|
||||
// 设置层数选点策略,相关逻辑在 RoguelikeStrategyChangeTaskPlugin
|
||||
{
|
||||
@@ -144,7 +148,6 @@ bool asst::RoguelikeTask::set_params(const json::value& params)
|
||||
params.get("investment_enabled", true) ? INT_MAX : 0);
|
||||
m_roguelike_task_ptr->set_times_limit("StageTraderRefreshWithDice",
|
||||
params.get("refresh_trader_with_dice", false) ? INT_MAX : 0);
|
||||
m_roguelike_task_ptr->set_times_limit("StageTraderInvestConfirm", params.get("investments_count", INT_MAX));
|
||||
|
||||
if (params.get("stop_when_investment_full", false)) {
|
||||
constexpr int InvestLimit = 999;
|
||||
|
||||
@@ -55,6 +55,10 @@ namespace asst
|
||||
bool get_start_with_elite_two() const { return m_start_with_elite_two; }
|
||||
void set_only_start_with_elite_two(bool value) { m_only_start_with_elite_two = value; }
|
||||
bool get_only_start_with_elite_two() const { return m_only_start_with_elite_two; }
|
||||
void set_invest_maximum(int value) { m_invest_maximum = value; }
|
||||
int get_invest_maximum() const { return m_invest_maximum; }
|
||||
void set_invest_stop_when_full(bool value) { m_invest_stop_when_full = value; }
|
||||
bool get_invest_stop_when_full() const { return m_invest_stop_when_full; }
|
||||
|
||||
private:
|
||||
std::string m_theme; // 主题
|
||||
@@ -62,6 +66,8 @@ namespace asst
|
||||
int m_difficulty = 0; // 难度
|
||||
bool m_start_with_elite_two = false; // 在刷开局模式下凹开局干员精二直升
|
||||
bool m_only_start_with_elite_two = false; // 只凹开局干员精二直升且不进行作战
|
||||
int m_invest_maximum = 0; // 投资次数上限
|
||||
bool m_invest_stop_when_full = false; // 存款满了就停止
|
||||
|
||||
/* 以下为每次重置 */
|
||||
public:
|
||||
|
||||
129
src/MaaCore/Task/Roguelike/RoguelikeInvestTaskPlugin.cpp
Normal file
129
src/MaaCore/Task/Roguelike/RoguelikeInvestTaskPlugin.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "RoguelikeInvestTaskPlugin.h"
|
||||
|
||||
#include "Config/TaskData.h"
|
||||
#include "Controller/Controller.h"
|
||||
#include "Task/ProcessTask.h"
|
||||
#include "Utils/Logger.hpp"
|
||||
#include "Vision/RegionOCRer.h"
|
||||
|
||||
bool asst::RoguelikeInvestTaskPlugin::verify(AsstMsg msg, const json::value& details) const
|
||||
{
|
||||
if (msg != AsstMsg::SubTaskStart || details.get("subtask", std::string()) != "ProcessTask") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto task_name = details.get("details", "task", "");
|
||||
if (task_name.ends_with("Roguelike@StageTraderInvestConfirm")) {
|
||||
return m_invest_count < m_config->get_invest_maximum();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool asst::RoguelikeInvestTaskPlugin::_run()
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
auto image = ctrler()->get_image();
|
||||
|
||||
// 进入投资页面成功
|
||||
// 999 >> 1000
|
||||
// 取消 | 确认投资
|
||||
|
||||
int count = 0; // 当次已投资的个数
|
||||
int retry = 0; // 重试次数
|
||||
const auto ocr_current_count = [](const auto& img, const auto& task_name) -> std::optional<int> {
|
||||
RegionOCRer ocr(img);
|
||||
ocr.set_task_info(task_name);
|
||||
if (!ocr.analyze()) {
|
||||
Log.error(__FUNCTION__, "unable to analyze current investment count.");
|
||||
return std::nullopt;
|
||||
};
|
||||
int count = 0;
|
||||
if (!utils::chars_to_number(ocr.get_result().text, count)) {
|
||||
Log.error(__FUNCTION__, "unable to convert current investment count<", ocr.get_result().text,
|
||||
"> to number.");
|
||||
return std::nullopt;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
// 当前的存款
|
||||
auto deposit = ocr_current_count(image, "Roguelike@StageTraderInvest-Count");
|
||||
// 可用投资次数
|
||||
int count_limit = m_config->get_invest_maximum() - m_invest_count;
|
||||
// 投资确认按钮
|
||||
const auto& click_rect = Task.get("Roguelike@StageTraderInvest-Confirm")->specific_rect;
|
||||
Log.info(__FUNCTION__, "开始投资, 存款", deposit.value_or(-1), ", 可投资次数", count_limit);
|
||||
while (!need_exit() && deposit && *deposit < 999 && count_limit > 0 && retry < 3) {
|
||||
int times = std::min(15, count_limit - count);
|
||||
while (!need_exit() && times > 0) {
|
||||
ctrler()->click(click_rect);
|
||||
sleep(100);
|
||||
times--;
|
||||
}
|
||||
image = ctrler()->get_image();
|
||||
if (!is_investment_available(image)) { // 检查是否处于可投资状态
|
||||
break; // 投资系统错误 / 没钱了
|
||||
}
|
||||
else if (auto ocr = ocr_current_count(image, "Roguelike@StageTraderInvest-Count"); ocr) {
|
||||
// 可继续投资 / 到达投资上限999
|
||||
if (*ocr == *deposit || *ocr > 999 || *ocr < 1) {
|
||||
retry++; // 可能是出错了,重试三次放弃
|
||||
}
|
||||
else {
|
||||
count += *ocr - *deposit;
|
||||
deposit = *ocr;
|
||||
retry = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log.error(__FUNCTION__, "未知状态");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto ocr = ocr_current_count(ctrler()->get_image(), "Roguelike@StageTrader-InvestCount"); ocr) {
|
||||
// 可继续投资 / 到达投资上限999
|
||||
count += *ocr - deposit.value_or(0);
|
||||
deposit = *ocr;
|
||||
}
|
||||
|
||||
const auto total = count + m_invest_count;
|
||||
|
||||
auto info = basic_info_with_what("RoguelikeInvestment");
|
||||
info["details"]["count"] = count;
|
||||
info["details"]["total"] = total;
|
||||
info["details"]["deposit"] = deposit ? *deposit : -1;
|
||||
callback(AsstMsg::SubTaskExtraInfo, info);
|
||||
|
||||
Log.info(__FUNCTION__, "本轮投资结束, 投资", count, ", 共投资", total, "; 系统余额", deposit ? *deposit : -1);
|
||||
m_invest_count = total;
|
||||
|
||||
if (count_limit - count <= 0) {
|
||||
Log.info(__FUNCTION__, "投资达到设置上限,", m_config->get_invest_maximum());
|
||||
stop_roguelike();
|
||||
m_task_ptr->set_enable(false);
|
||||
return true;
|
||||
}
|
||||
if (deposit.value_or(0) == 999 && m_config->get_invest_stop_when_full()) {
|
||||
Log.info(__FUNCTION__, "存款已满");
|
||||
stop_roguelike();
|
||||
m_task_ptr->set_enable(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool asst::RoguelikeInvestTaskPlugin::is_investment_available(const cv::Mat& image) const
|
||||
{
|
||||
auto task = ProcessTask(*this, { "Roguelike@StageTraderInvest-Arrow", "Roguelike@StageTraderInvestSystemError" });
|
||||
task.set_reusable_image(image).set_retry_times(3);
|
||||
task.set_times_limit("Roguelike@StageTraderInvestCancel", 0);
|
||||
return task.run() && task.get_last_task_name() == "Roguelike@StageTraderInvest-Arrow";
|
||||
}
|
||||
|
||||
void asst::RoguelikeInvestTaskPlugin::stop_roguelike()
|
||||
{
|
||||
dynamic_cast<ProcessTask*>(m_task_ptr)->set_times_limit("Roguelike@StageTraderInvestConfirm", 0);
|
||||
}
|
||||
21
src/MaaCore/Task/Roguelike/RoguelikeInvestTaskPlugin.h
Normal file
21
src/MaaCore/Task/Roguelike/RoguelikeInvestTaskPlugin.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "AbstractRoguelikeTaskPlugin.h"
|
||||
|
||||
namespace asst
|
||||
{
|
||||
// 肉鸽投资插件
|
||||
class RoguelikeInvestTaskPlugin : public AbstractRoguelikeTaskPlugin
|
||||
{
|
||||
public:
|
||||
using AbstractRoguelikeTaskPlugin::AbstractRoguelikeTaskPlugin;
|
||||
virtual ~RoguelikeInvestTaskPlugin() override = default;
|
||||
virtual bool verify(AsstMsg msg, const json::value& details) const override;
|
||||
|
||||
private:
|
||||
virtual bool _run() override;
|
||||
bool is_investment_available(const cv::Mat& image) const;
|
||||
void stop_roguelike();
|
||||
|
||||
int m_invest_count = 0;
|
||||
};
|
||||
} // namespace asst
|
||||
@@ -1175,6 +1175,11 @@ namespace MaaWpfGui.Main
|
||||
break;
|
||||
}
|
||||
|
||||
case "RoguelikeInvestment":
|
||||
Instances.TaskQueueViewModel.AddLog(string.Format(LocalizationHelper.GetString("RoguelikeInvestment"), subTaskDetails["count"], subTaskDetails["total"], subTaskDetails["deposit"]), UiLogColor.Info);
|
||||
break;
|
||||
|
||||
|
||||
case "RoguelikeSettlement":
|
||||
// 肉鸽结算
|
||||
bool roguelikeGamePass = (bool)subTaskDetails["game_pass"];
|
||||
|
||||
@@ -634,6 +634,7 @@ The video aspect ratio needs to be 16:9 without interference factors such as bla
|
||||
<system:String x:Key="EmergencyDps">Node: Emergency Operation</system:String>
|
||||
<system:String x:Key="DreadfulFoe">Node: Dreadful Foe</system:String>
|
||||
<system:String x:Key="RoguelikeEvent">Event:</system:String>
|
||||
<system:String x:Key="RoguelikeInvestment">Invested {1}(+{0}), deposit: {2}</system:String>
|
||||
<system:String x:Key="RoguelikeSettlement">Roguelike Settlement: {0}\nExplore: {1} Floor {2} Step\nCombat: {3} / {4} Emergency / {5} BOSS\nRecruit: {6}\nCollectibles: {7}\nDifficulty: {8}\nScore: {9}\nExp: {10}, Skill: {11}</system:String>
|
||||
<system:String x:Key="CurTimes">Current times</system:String>
|
||||
<system:String x:Key="NoDrop">Nothing</system:String>
|
||||
|
||||
@@ -634,6 +634,7 @@ Bilibili: ログイン インターフェイスに表示されるアカウント
|
||||
<system:String x:Key="EmergencyDps">ステージ: 緊急作戦</system:String>
|
||||
<system:String x:Key="DreadfulFoe">ステージ: 悪路凶敵</system:String>
|
||||
<system:String x:Key="RoguelikeEvent">イベント:</system:String>
|
||||
<system:String x:Key="RoguelikeInvestment">投資済み: {1}(+{0})、デポジット: {2}</system:String>
|
||||
<system:String x:Key="RoguelikeSettlement">ローグライク決済: {0}\n探検する: {1} 床 {2} ステップ\n戦闘: {3} / {4} 緊急 / {5} BOSS\nリクルート: {6}\nコレクション: {7}\n困難: {8}\nスコア: {9}\n経験値: {10}, スキル: {11}</system:String>
|
||||
<system:String x:Key="CurTimes">現在の回数</system:String>
|
||||
<system:String x:Key="NoDrop">ドロップなし</system:String>
|
||||
|
||||
@@ -634,6 +634,7 @@ Bilibili: 로그인 인터페이스에 표시되는 계정 이름(예: 장산)
|
||||
<system:String x:Key="EmergencyDps">레벨: 긴급 작전</system:String>
|
||||
<system:String x:Key="DreadfulFoe">레벨: 험난한 길</system:String>
|
||||
<system:String x:Key="RoguelikeEvent">이벤트:</system:String>
|
||||
<system:String x:Key="RoguelikeInvestment">투자: {1}(+{0}), 예금: {2}</system:String>
|
||||
<system:String x:Key="RoguelikeSettlement">로그라이크 종착점: {0}\n클리어 : {1} 구역 {2} 노드\n전투 횟수: {3} 일반 / {4} 정예 / {5} 리더\n모집 횟수 : {6} 회\n수집: {7}\n난이도: {8}\n점수: {9}\n경험치: {10}, 스킬: {11}</system:String>
|
||||
<system:String x:Key="CurTimes">현재 횟수</system:String>
|
||||
<system:String x:Key="NoDrop">없음</system:String>
|
||||
|
||||
@@ -634,6 +634,7 @@
|
||||
<system:String x:Key="EmergencyDps">关卡: 紧急作战</system:String>
|
||||
<system:String x:Key="DreadfulFoe">关卡: 险路恶敌</system:String>
|
||||
<system:String x:Key="RoguelikeEvent">事件:</system:String>
|
||||
<system:String x:Key="RoguelikeInvestment">已投资 {1}(+{0}), 存款: {2}</system:String>
|
||||
<system:String x:Key="RoguelikeSettlement">肉鸽结算: {0}\n探索: {1} 层 {2} 步\n战斗: {3}/{4} 紧急/{5} BOSS\n招募: {6} 收藏品: {7}\n难度: {8} 得分: {9}\nExp: {10} Skill: {11}</system:String>
|
||||
<system:String x:Key="CurTimes">当前次数</system:String>
|
||||
<system:String x:Key="NoDrop">无</system:String>
|
||||
|
||||
@@ -632,6 +632,7 @@
|
||||
<system:String x:Key="EmergencyDps">關卡: 緊急作戰</system:String>
|
||||
<system:String x:Key="DreadfulFoe">關卡: 險路惡敵</system:String>
|
||||
<system:String x:Key="RoguelikeEvent">事件:</system:String>
|
||||
<system:String x:Key="RoguelikeInvestment">已投資 {1}(+{0}), 存款: {2}</system:String>
|
||||
<system:String x:Key="RoguelikeSettlement">肉鴿結算: {0}\n探索: {1} 层 {2} 步\n戰鬥: {3}/{4} 緊急/{5} BOSS\n招募: {6} 收藏品: {7}\n難度: {8} 得分: {9}\nExp: {10} Skill: {11}</system:String>
|
||||
<system:String x:Key="CurTimes">目前次數</system:String>
|
||||
<system:String x:Key="NoDrop">無</system:String>
|
||||
|
||||
Reference in New Issue
Block a user