Files
MaaAssistantArknights/src/MaaCore/Task/Interface/RoguelikeTask.cpp
travellerse 965a762e8a feat: 适配界园肉鸽通宝交换 (#13835)
* feat: 初步实现界园肉鸽通宝交换

* feat: 实现通宝交换后弹窗点击

* fix: 使用ocr作为通宝交换完成的标志

* fix: 给通宝弹窗确认的 pre_task 加上 postDelay

* fix: 小错误修改

* fix: 添加ocrReplace

* feat: 给通宝赋予临时权重,之后再改

* refactor: 重构通宝任务插件,拆分复杂的_run

* fix: 修正通宝选择点击错误

* refactor: 把滑动函数改回直观

* feat: 新增已投出时的通宝丢弃权重

* fix: 更新通宝名称匹配规则

* chore: 增加注释和日志输出

* chore: 添加调试截图保存

* fix: 清理未使用的参数

* fix: 微调通宝权重

* fix: 修正保存截图过多

* fix: 修复Rect不匹配造成的错误

* fix: 调整debug截图

* fix: 修正选择通宝时位置错误

* fix: 修复刷不交换通宝时无法退出

* fix: 修改`已投出`识别得分的绘制位置

* fix: 启用不期而遇`饕餮廊`获取通宝

* fix: 调整通宝识别区域宽度

* fix: 添加`厉-安硕` -> `厉-安硕鼷`的替换

* fix: 为通宝名称未匹配产生的debug截图添加方框

* fix: 修正debug截图方框位置

* fix: 清理无用的ocrReplace

* fix: 删除通过任务给插件传递特殊参数

* fix: 增加"衡-霹雳"和"花-圣诏封神"的ocr替换

* docs: 添加界园肉鸽通宝交换文档

* fix: 默认刷开局模式交换通宝

* fix: 删除未使用的通宝列表行数变量

* fix: 通宝交换完成识别增加延迟

* fix: 增加"衡-军屯垦"的ocr替换

* chore: Auto update by pre-commit hooks [skip changelog]

* fix: 修正调试图像保存路径

* perf: 优化通宝创建逻辑

* refactor: 更新通宝任务模式名称

* refactor: 更新通宝稀有度键值

* chore: 更新通宝优先级

* fix: 通宝列表匹配时可能会将y轴间隔覆盖为0

* perf: 将交换通宝的信息发送到wpf

* perf: 将通宝调试截图改为jpeg

* fix:  添加"衡-旱热"的ocr替换

* refactor: 传递任务执行结果

* feat: 初步动态识别通宝列表

* perf: 将期望为空的识别逻辑改为期望匹配到

* chore: 为通宝类型模板添加mask

* refactor: 重构通宝识别逻辑

* refactor: 提取保存调试图像

* refactor: 使用std::format优化日志输出

* refactor: 收尾

* chore: 微调滑动距离

* fix: 忘了加maskRange了

* chore: 保留score小数点后六位

* fix: 修复神秘的点击停止后卡死问题

* docs: 更新文档

* docs: 添加通宝识别流程示意图

* fix: 更新通宝稀有度定义

* chore: 添加通宝交换模式的图片示意注释

* chore: 加点注释

* perf: 预分配通宝和检测结果的空间

* chore: 优化运行时状态变量注释

* fix: 仅在确实已被投出时绘制已投出的调试方框

* fix: 修正坐标变量名称以符合语义

* perf: 滑动误差较大时额外滑动一次进行回正

* fix: 仅在缓慢滑动时校准位置

* refactor: 优化通宝列表滑动

* fix: 尝试修复偶发通宝最后一列无法识别

* fix: 移除了 999

* fix: 进一步修复滑动

* chore: 更新未知通宝调试图像保存路径

* fix: 更改调试截图保存位置和matcher使用图片初始化

* fix: 添加"厉-一字落"的ocr替换

* fix: 适配MaaUtils的更改

* chore: 调整任务顺序

* chore: 添加通宝重投和开关钱盒任务配置

* chore: 文件头/注释调整

* rft: meojson反序列化

* chore: Auto update by pre-commit hooks [skip changelog]

* perf: 替换部分新log输出

* i18n: KR

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: status102 <102887808+status102@users.noreply.github.com>
Co-authored-by: HX3N <scarlet7518@gmail.com>
2025-11-19 15:22:33 +08:00

203 lines
9.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "RoguelikeTask.h"
#include "Common/AsstBattleDef.h"
#include "Config/TaskData.h"
#include "Task/ProcessTask.h"
// ------------------ 通用配置及插件 ------------------
#include "Task/Miscellaneous/ScreenshotTaskPlugin.h"
#include "Task/Roguelike/RoguelikeBattleTaskPlugin.h"
#include "Task/Roguelike/RoguelikeConfig.h"
#include "Task/Roguelike/RoguelikeControlTaskPlugin.h"
#include "Task/Roguelike/RoguelikeCustomStartTaskPlugin.h"
#include "Task/Roguelike/RoguelikeDebugTaskPlugin.h"
#include "Task/Roguelike/RoguelikeDifficultySelectionTaskPlugin.h"
#include "Task/Roguelike/RoguelikeFormationTaskPlugin.h"
#include "Task/Roguelike/RoguelikeInvestTaskPlugin.h"
#include "Task/Roguelike/RoguelikeIterateDeepExplorationPlugin.h"
#include "Task/Roguelike/RoguelikeIterateMonthlySquadPlugin.h"
#include "Task/Roguelike/RoguelikeLastRewardTaskPlugin.h"
#include "Task/Roguelike/RoguelikeLevelTaskPlugin.h"
#include "Task/Roguelike/RoguelikeRecruitTaskPlugin.h"
#include "Task/Roguelike/RoguelikeResetTaskPlugin.h"
#include "Task/Roguelike/RoguelikeSettlementTaskPlugin.h"
#include "Task/Roguelike/RoguelikeShoppingTaskPlugin.h"
#include "Task/Roguelike/RoguelikeSkillSelectionTaskPlugin.h"
#include "Task/Roguelike/RoguelikeStageEncounterTaskPlugin.h"
#include "Task/Roguelike/RoguelikeStrategyChangeTaskPlugin.h"
// ------------------ 萨米主题专用配置及插件 ------------------
#include "Config/Roguelike/Sami/RoguelikeCollapsalParadigmConfig.h"
#include "Task/Roguelike/Sami/RoguelikeCollapsalParadigmTaskPlugin.h"
#include "Task/Roguelike/Sami/RoguelikeFoldartalGainTaskPlugin.h"
#include "Task/Roguelike/Sami/RoguelikeFoldartalStartTaskPlugin.h"
#include "Task/Roguelike/Sami/RoguelikeFoldartalUseTaskPlugin.h"
// ------------------ 萨卡兹主题专用配置及插件 ------------------
#include "Task/Roguelike/RoguelikeInputSeedTaskPlugin.h"
// ------------------ 导航相关配置及插件 ------------------
#include "Task/Roguelike/Map/RoguelikeBoskyPassageRoutingTaskPlugin.h"
#include "Task/Roguelike/Map/RoguelikeRoutingTaskPlugin.h"
// ------------------ 界园主题专用配置及插件 ------------------
#include "Task/Roguelike/JieGarden/RoguelikeCoppersTaskPlugin.h"
#include "Utils/Logger.hpp"
asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, Assistant* inst) :
InterfaceTask(callback, inst, TaskType),
m_roguelike_task_ptr(std::make_shared<ProcessTask>(callback, inst, TaskType)),
m_config_ptr(std::make_shared<RoguelikeConfig>())
{
LogTraceFunction;
// m_roguelike_task_ptr->set_ignore_error(true);
m_control_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeControlTaskPlugin>(m_config_ptr);
// ------------------ 通用插件 ------------------
m_roguelike_task_ptr->register_plugin<ScreenshotTaskPlugin>();
m_roguelike_task_ptr->register_plugin<RoguelikeFormationTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeResetTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeSettlementTaskPlugin>(m_config_ptr, m_control_ptr);
m_invest_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeInvestTaskPlugin>(m_config_ptr, m_control_ptr);
m_debug_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeDebugTaskPlugin>(m_config_ptr, m_control_ptr);
m_custom_ptr = m_roguelike_task_ptr->register_plugin<RoguelikeCustomStartTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeShoppingTaskPlugin>(m_config_ptr, m_control_ptr)->set_retry_times(0);
m_roguelike_task_ptr->register_plugin<RoguelikeBattleTaskPlugin>(m_config_ptr, m_control_ptr)
->set_retry_times(0)
.set_ignore_error(true);
m_roguelike_task_ptr->register_plugin<RoguelikeRecruitTaskPlugin>(m_config_ptr, m_control_ptr)
->set_retry_times(2)
.set_ignore_error(true);
m_roguelike_task_ptr->register_plugin<RoguelikeSkillSelectionTaskPlugin>(m_config_ptr, m_control_ptr)
->set_retry_times(2)
.set_ignore_error(true);
m_roguelike_task_ptr->register_plugin<RoguelikeStageEncounterTaskPlugin>(m_config_ptr, m_control_ptr)
->set_retry_times(0);
m_roguelike_task_ptr->register_plugin<RoguelikeLastRewardTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeDifficultySelectionTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeStrategyChangeTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeIterateMonthlySquadPlugin>(m_config_ptr, m_control_ptr)
->set_retry_times(3);
m_roguelike_task_ptr->register_plugin<RoguelikeIterateDeepExplorationPlugin>(m_config_ptr, m_control_ptr)
->set_retry_times(3);
m_roguelike_task_ptr->register_plugin<RoguelikeLevelTaskPlugin>(m_config_ptr, m_control_ptr);
// ------------------ 萨米主题专用插件 ------------------
m_roguelike_task_ptr->register_plugin<RoguelikeFoldartalGainTaskPlugin>(m_config_ptr, m_control_ptr);
m_foldartal_use_ptr =
m_roguelike_task_ptr->register_plugin<RoguelikeFoldartalUseTaskPlugin>(m_config_ptr, m_control_ptr);
m_foldartal_start_ptr =
m_roguelike_task_ptr->register_plugin<RoguelikeFoldartalStartTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeCollapsalParadigmTaskPlugin>(m_config_ptr, m_control_ptr);
// ------------------ 萨卡兹主题专用插件 ------------------
m_roguelike_task_ptr->register_plugin<RoguelikeInputSeedTaskPlugin>(m_config_ptr, m_control_ptr);
// ------------------ 导航相关插件 ------------------
m_roguelike_task_ptr->register_plugin<RoguelikeRoutingTaskPlugin>(m_config_ptr, m_control_ptr);
m_roguelike_task_ptr->register_plugin<RoguelikeBoskyPassageRoutingTaskPlugin>(m_config_ptr, m_control_ptr);
// ------------------ 界园主题专用插件 ------------------
m_roguelike_task_ptr->register_plugin<RoguelikeCoppersTaskPlugin>(m_config_ptr, m_control_ptr);
m_subtasks.emplace_back(m_roguelike_task_ptr);
}
bool asst::RoguelikeTask::set_params(const json::value& params)
{
LogTraceFunction;
if (m_running) {
Log.warn(__FUNCTION__, "RoguelikeTask is running, cannot set params");
return false;
}
if (!m_config_ptr->verify_and_load_params(params)) {
m_roguelike_task_ptr->set_tasks({ "Stop" });
return false;
}
const auto& theme = m_config_ptr->get_theme();
const auto& mode = m_config_ptr->get_mode();
m_roguelike_task_ptr->set_tasks({ theme + "@Roguelike@Begin" });
if (mode == RoguelikeMode::Investment) {
// 刷源石锭模式是否进入第二层
if (m_config_ptr->get_invest_with_more_score()) {
// 战斗后奖励默认
Task.set_task_base(theme + "@Roguelike@DropsFlag", theme + "@Roguelike@DropsFlag_default");
m_roguelike_task_ptr->set_times_limit("StageTraderInvestCancel", INT_MAX);
if (theme == RoguelikeTheme::JieGarden) {
m_roguelike_task_ptr->set_times_limit("StageTraderLeaveConfirm", INT_MAX);
}
else {
m_roguelike_task_ptr->set_times_limit("StageTraderLeaveConfirm", 0, ProcessTask::TimesLimitType::Post);
}
}
else {
// 战斗后奖励只拿钱
Task.set_task_base(theme + "@Roguelike@DropsFlag", theme + "@Roguelike@DropsFlag_mode1");
m_roguelike_task_ptr->set_times_limit("StageTraderInvestCancel", 0);
m_roguelike_task_ptr->set_times_limit("StageTraderLeaveConfirm", INT_MAX);
}
}
else {
// 重置战斗后奖励next
Task.set_task_base(theme + "@Roguelike@DropsFlag", theme + "@Roguelike@DropsFlag_default");
m_roguelike_task_ptr->set_times_limit("StageTraderInvestCancel", INT_MAX);
m_roguelike_task_ptr->set_times_limit("StageTraderLeaveConfirm", INT_MAX);
}
bool stop_at_final_boss = params.get("stop_at_final_boss", false);
// 傀影肉鸽3层和5层boss图标一样,禁用
if (stop_at_final_boss && theme != RoguelikeTheme::Phantom) {
m_roguelike_task_ptr->set_times_limit(theme + "@Roguelike@StageDreadfulFoe-5", 0);
}
else {
// 重置boss进点
m_roguelike_task_ptr->set_times_limit(theme + "@Roguelike@StageDreadfulFoe-5", INT_MAX);
}
if (theme == RoguelikeTheme::Sami) {
if (auto opt = params.find<json::array>("start_foldartal_list"); opt) {
std::vector<std::string> list;
for (const auto& name : *opt) {
if (std::string name_str = name.as_string(); !name_str.empty()) {
list.emplace_back(name_str);
}
}
/* 由于插件 load_param返回值仅决定自身是否启用二次读取参数进行验证 */
if (list.empty()) {
Log.error(__FUNCTION__, "| Empty start_foldartal_list");
return false;
}
}
}
m_roguelike_task_ptr->set_times_limit(theme + "@Roguelike@StartExplore", params.get("starts_count", INT_MAX));
// 通过 exceededNext 禁用投资系统,进入商店购买逻辑
m_roguelike_task_ptr->set_times_limit(
"StageTraderInvestSystem",
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);
for (const auto& plugin : m_roguelike_task_ptr->get_plugins()) {
if (const auto& p_ptr = std::dynamic_pointer_cast<AbstractRoguelikeTaskPlugin>(plugin); p_ptr != nullptr) {
p_ptr->set_enable(p_ptr->load_params(params));
}
}
return true;
}