diff --git a/resource/roguelike_shopping.json b/resource/roguelike_shopping.json
index 670d1abfe1..8946f9dd82 100644
--- a/resource/roguelike_shopping.json
+++ b/resource/roguelike_shopping.json
@@ -1,22 +1,30 @@
[
{
- "name": "金酒之杯"
+ "name": "金酒之杯",
+ "no_longer_buy": true,
+ "ignore_no_longer_buy": true
},
{
- "name": "投币玩具"
+ "name": "投币玩具",
+ "no_longer_buy": true,
+ "ignore_no_longer_buy": true
},
{
- "name": "骑士戒律·新编"
+ "name": "骑士戒律·新编",
+ "no_longer_buy": true,
+ "ignore_no_longer_buy": true
},
{
"name": "人事部密信"
},
{
- "name": "Miss.Christine摸摸券"
+ "name": "Miss.Christine摸摸券",
+ "promotion": 2
},
{
"name": "残弩-典训",
- "role": "SNIPER"
+ "role": "SNIPER",
+ "promotion": 1
},
{
"name": "绿叶菜罐头"
@@ -45,7 +53,8 @@
"name": "锈蚀的铁锤"
},
{
- "name": "尖笑鬼牌"
+ "name": "尖笑鬼牌",
+ "promotion": 1
},
{
"name": "赤金的远征"
@@ -70,7 +79,8 @@
},
{
"name": "折戟-典训",
- "role": "WARRIOR"
+ "role": "WARRIOR",
+ "promotion": 1
},
{
"name": "全局作战文件"
@@ -87,7 +97,8 @@
},
{
"name": "钝爪-典训",
- "role": "PIONEER"
+ "role": "PIONEER",
+ "promotion": 1
},
{
"name": "皇家利口酒"
@@ -104,7 +115,8 @@
},
{
"name": "断杖-典训",
- "role": "CASTER"
+ "role": "CASTER",
+ "promotion": 1
},
{
"name": "高卢小圆饼"
@@ -207,7 +219,8 @@
},
{
"name": "支柱-典训",
- "role": "SUPPORT"
+ "role": "SUPPORT",
+ "promotion": 1
},
{
"name": "皇帝的收藏"
@@ -219,7 +232,8 @@
"name": "香草沙士汽水"
},
{
- "name": "幸运硬币"
+ "name": "幸运硬币",
+ "ignore_no_longer_buy": true
},
{
"name": "镶金骨骰"
@@ -238,7 +252,8 @@
"role": "PIONEER"
},
{
- "name": "至宝指环"
+ "name": "至宝指环",
+ "ignore_no_longer_buy": true
},
{
"name": "残弩-战场依存",
@@ -396,7 +411,8 @@
"name": "凯旋号角"
},
{
- "name": "假面舞会面具"
+ "name": "假面舞会面具",
+ "ignore_no_longer_buy": true
},
{
"name": "奇渊面具"
diff --git a/resource/tasks.json b/resource/tasks.json
index 39950a8d88..d18c5136e2 100644
--- a/resource/tasks.json
+++ b/resource/tasks.json
@@ -6785,6 +6785,12 @@
750,
280
],
+ "rectMove": [
+ -40,
+ -100,
+ 20,
+ 60
+ ],
"next": [
"Roguelike1TraderRandomShoppingConfirm",
"Roguelike1TraderRandomShoppingCancel",
@@ -6823,40 +6829,6 @@
]
},
- "Roguelike1TraderShoppingConfirm": {
- "template": "Roguelike1TraderRandomShoppingConfirm.png",
- "action": "ClickSelf",
- "cache": false,
- "roi": [
- 872,
- 425,
- 221,
- 136
- ],
- "rectMove": [
- -40,
- -100,
- 20,
- 60
- ],
- "rearDelay": 2000,
- "Doc": "当网络卡的时候才会发生点了确认,但是还可以点取消的情况",
- "next": [
- "Roguelike1TraderShoppingConfirmedFlag",
- "Roguelike1ChooseOperFlag"
- ]
- },
- "Roguelike1TraderShoppingConfirmedFlag": {
- "template": "Roguelike1StageTraderLeave.png",
- "action": "DoNothing",
- "cache": false,
- "roi": [
- 1046,
- 443,
- 234,
- 204
- ]
- },
"Roguelike1TraderShoppingOver": {
"template": "Roguelike1StageTraderLeave.png",
"action": "ClickSelf",
diff --git a/src/MeoAssistant/AsstBattleDef.h b/src/MeoAssistant/AsstBattleDef.h
index 48d3df0921..4d52c62d55 100644
--- a/src/MeoAssistant/AsstBattleDef.h
+++ b/src/MeoAssistant/AsstBattleDef.h
@@ -102,7 +102,7 @@ namespace asst
Rect rect;
cv::Mat avatar;
std::string name;
- size_t index;
+ size_t index = 0;
bool cooling = false;
};
diff --git a/src/MeoAssistant/MeoAssistant.vcxproj b/src/MeoAssistant/MeoAssistant.vcxproj
index 35bcc63408..b7070f3fb9 100644
--- a/src/MeoAssistant/MeoAssistant.vcxproj
+++ b/src/MeoAssistant/MeoAssistant.vcxproj
@@ -89,6 +89,7 @@
+
@@ -178,6 +179,7 @@
+
diff --git a/src/MeoAssistant/MeoAssistant.vcxproj.filters b/src/MeoAssistant/MeoAssistant.vcxproj.filters
index a7883b5f22..aff2f6e5a3 100644
--- a/src/MeoAssistant/MeoAssistant.vcxproj.filters
+++ b/src/MeoAssistant/MeoAssistant.vcxproj.filters
@@ -363,6 +363,9 @@
头文件\Task\Plugin\Roguelike
+
+ 头文件\Task\Plugin\Roguelike
+
@@ -626,6 +629,9 @@
源文件\Task\Plugin\Roguelike
+
+ 源文件\Task\Plugin\Roguelike
+
diff --git a/src/MeoAssistant/ProcessTask.cpp b/src/MeoAssistant/ProcessTask.cpp
index 86020c1701..51ac669607 100644
--- a/src/MeoAssistant/ProcessTask.cpp
+++ b/src/MeoAssistant/ProcessTask.cpp
@@ -95,14 +95,14 @@ bool ProcessTask::_run()
};
Log.info(info.to_string());
- Rect rect;
-
auto front_task_ptr = Task.get(m_cur_tasks_name.front());
// 可能有配置错误,导致不存在对应的任务
if (front_task_ptr == nullptr) {
Log.error("Invalid task", m_cur_tasks_name.front());
return false;
}
+
+ Rect rect;
// 如果第一个任务是JustReturn的,那就没必要再截图并计算了
if (front_task_ptr->algorithm == AlgorithmType::JustReturn) {
m_cur_task_ptr = front_task_ptr;
diff --git a/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp b/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp
index 33155cb8c5..517a7c75b9 100644
--- a/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp
+++ b/src/MeoAssistant/RoguelikeRecruitTaskPlugin.cpp
@@ -131,6 +131,15 @@ bool asst::RoguelikeRecruitTaskPlugin::check_core_char()
void asst::RoguelikeRecruitTaskPlugin::select_oper(const BattleRecruitOperInfo& oper)
{
m_ctrler->click(oper.rect);
+
m_status->set_number(RuntimeStatus::RoguelikeCharElitePrefix + oper.name, oper.elite);
m_status->set_number(RuntimeStatus::RoguelikeCharLevelPrefix + oper.name, oper.level);
+
+ std::string overview_str = m_status->get_str(RuntimeStatus::RoguelikeCharOverview).value_or(json::value().to_string());
+ json::value overview = json::parse(overview_str).value_or(json::value());
+ overview[oper.name] = json::object{
+ { "elite", oper.elite },
+ { "level", oper.level },
+ };
+ m_status->set_str(RuntimeStatus::RoguelikeCharOverview, overview.to_string());
}
diff --git a/src/MeoAssistant/RoguelikeResetTaskPlugin.cpp b/src/MeoAssistant/RoguelikeResetTaskPlugin.cpp
new file mode 100644
index 0000000000..7d8e2d6458
--- /dev/null
+++ b/src/MeoAssistant/RoguelikeResetTaskPlugin.cpp
@@ -0,0 +1,26 @@
+#include "RoguelikeResetTaskPlugin.h"
+
+#include "RuntimeStatus.h"
+
+bool asst::RoguelikeResetTaskPlugin::verify(AsstMsg msg, const json::value& details) const
+{
+ if (msg != AsstMsg::SubTaskStart
+ || details.get("subtask", std::string()) != "ProcessTask") {
+ return false;
+ }
+
+ if (details.at("details").at("task").as_string() == "Roguelike1Start") {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool asst::RoguelikeResetTaskPlugin::_run()
+{
+ // 简单粗暴,后面如果多任务间有联动可能要改改
+ m_status->clear_number();
+ m_status->clear_str();
+ return true;
+}
diff --git a/src/MeoAssistant/RoguelikeResetTaskPlugin.h b/src/MeoAssistant/RoguelikeResetTaskPlugin.h
new file mode 100644
index 0000000000..e8483432a0
--- /dev/null
+++ b/src/MeoAssistant/RoguelikeResetTaskPlugin.h
@@ -0,0 +1,17 @@
+#pragma once
+#include "AbstractTaskPlugin.h"
+
+namespace asst
+{
+ class RoguelikeResetTaskPlugin : public AbstractTaskPlugin
+ {
+ public:
+ using AbstractTaskPlugin::AbstractTaskPlugin;
+ virtual ~RoguelikeResetTaskPlugin() = default;
+
+ virtual bool verify(AsstMsg msg, const json::value& details) const override;
+
+ protected:
+ virtual bool _run() override;
+ };
+}
diff --git a/src/MeoAssistant/RoguelikeShoppingConfiger.cpp b/src/MeoAssistant/RoguelikeShoppingConfiger.cpp
index a4c59a8b2a..4d6e7b5034 100644
--- a/src/MeoAssistant/RoguelikeShoppingConfiger.cpp
+++ b/src/MeoAssistant/RoguelikeShoppingConfiger.cpp
@@ -4,8 +4,8 @@
bool asst::RoguelikeShoppingConfiger::parse(const json::value& json)
{
- for (const auto& commodity_json : json.as_array()) {
- std::string name = commodity_json.at("name").as_string();
+ for (const auto& goods_json : json.as_array()) {
+ std::string name = goods_json.at("name").as_string();
static const std::unordered_map RoleMap = {
{ "CASTER", BattleRole::Caster },
{ "MEDIC", BattleRole::Medic },
@@ -17,11 +17,18 @@ bool asst::RoguelikeShoppingConfiger::parse(const json::value& json)
{ "WARRIOR", BattleRole::Warrior},
};
BattleRole role = BattleRole::Unknown;
- std::string str_role = commodity_json.get("role", "");
+ std::string str_role = goods_json.get("role", "");
if (!str_role.empty()) {
role = RoleMap.at(str_role);
}
- m_goods.emplace_back(RoguelikeGoods{ name, role });
+ RoguelikeGoods goods;
+ goods.name = std::move(name);
+ goods.role_restriction = role;
+ goods.promotion = goods_json.get("promotion", 0);
+ goods.no_longer_buy = goods_json.get("no_longer_buy", false);
+ goods.ignore_no_longer_buy = goods_json.get("ignore_no_longer_buy", false);
+
+ m_goods.emplace_back(std::move(goods));
}
return true;
}
diff --git a/src/MeoAssistant/RoguelikeShoppingConfiger.h b/src/MeoAssistant/RoguelikeShoppingConfiger.h
index b743ea1164..e1f5ce30f5 100644
--- a/src/MeoAssistant/RoguelikeShoppingConfiger.h
+++ b/src/MeoAssistant/RoguelikeShoppingConfiger.h
@@ -11,7 +11,10 @@ namespace asst
struct RoguelikeGoods
{
std::string name;
- BattleRole restriction = BattleRole::Unknown;
+ BattleRole role_restriction = BattleRole::Unknown;
+ int promotion = 0; // 晋升 N 个干员
+ bool no_longer_buy = false;
+ bool ignore_no_longer_buy = false;
};
class RoguelikeShoppingConfiger : public AbstractConfiger
diff --git a/src/MeoAssistant/RoguelikeShoppingTaskPlugin.cpp b/src/MeoAssistant/RoguelikeShoppingTaskPlugin.cpp
index 99eada2515..ee536ac23e 100644
--- a/src/MeoAssistant/RoguelikeShoppingTaskPlugin.cpp
+++ b/src/MeoAssistant/RoguelikeShoppingTaskPlugin.cpp
@@ -5,6 +5,7 @@
#include "Controller.h"
#include "ProcessTask.h"
#include "Logger.hpp"
+#include "RuntimeStatus.h"
bool asst::RoguelikeShoppingTaskPlugin::verify(AsstMsg msg, const json::value& details) const
{
@@ -32,19 +33,55 @@ bool asst::RoguelikeShoppingTaskPlugin::_run()
if (!analyzer.analyze()) {
return false;
}
+
+ bool no_longer_buy =
+ m_status->get_number(RuntimeStatus::RoguelikeTraderNoLongerBuy).value_or(0)
+ ? true : false;
+
+ std::string str_chars_info =
+ m_status->get_str(RuntimeStatus::RoguelikeCharOverview)
+ .value_or(json::value().to_string());
+ json::value json_chars_info = json::parse(str_chars_info).value_or(json::value());
+
+ std::unordered_map map_roles_count;
+ for (auto& [name, json_info] : json_chars_info.as_object()) {
+ int elite = static_cast(json_info.get("elite", 0));
+ int level = static_cast(json_info.get("level", 0));
+ Log.info(name, elite, level);
+
+ // 等级太低的干员没必要为他专门买收藏品什么的
+ if (elite * 1000 + level < 1070) {
+ continue;
+ }
+
+ if (name == "阿米娅") {
+ map_roles_count[BattleRole::Caster] += 1;
+ map_roles_count[BattleRole::Warrior] += 1;
+ }
+ else {
+ BattleRole role = BattleRole::Unknown;
+ auto int_role = json_info.get("role", 0);
+ if (int_role) {
+ role = static_cast(int_role);
+ }
+ else {
+ role = Resrc.battle_data().get_role(name);
+ }
+ map_roles_count[role] += 1;
+ }
+ }
+
const auto& result = analyzer.get_result();
const auto& order_goods_list = Resrc.roguelike_shopping().get_goods();
-
bool bought = false;
for (const auto& goods : order_goods_list) {
if (need_exit()) {
return false;
}
-
- if (goods.restriction != BattleRole::Unknown) {
- // TODO
+ if (no_longer_buy && !goods.ignore_no_longer_buy) {
continue;
}
+
auto find_it = std::find_if(result.cbegin(), result.cend(),
[&](const TextRect& tr) -> bool {
return tr.text.find(goods.name) != std::string::npos ||
@@ -53,12 +90,23 @@ bool asst::RoguelikeShoppingTaskPlugin::_run()
if (find_it == result.cend()) {
continue;
}
+
+ if (goods.role_restriction != BattleRole::Unknown
+ && map_roles_count[goods.role_restriction] == 0) {
+ Log.trace("Ready to buy", goods.name, static_cast(goods.role_restriction),
+ ", but there is no such professional operator, skip");
+ continue;
+ }
+
// 这里仅点一下收藏品,原本的 ProcessTask 还会再点一下,但它是由 rect_move 的,保证不会点出去
// 即 ProcessTask 多点的那一下会点到不影响的地方
// 然后继续走 next 里确认 or 取消等等的逻辑
Log.info("Ready to buy", goods.name);
m_ctrler->click(find_it->rect);
bought = true;
+ if (goods.no_longer_buy) {
+ m_status->set_number(RuntimeStatus::RoguelikeTraderNoLongerBuy, 1);
+ }
break;
}
diff --git a/src/MeoAssistant/RoguelikeTask.cpp b/src/MeoAssistant/RoguelikeTask.cpp
index 0acdfd8b45..f79c920a84 100644
--- a/src/MeoAssistant/RoguelikeTask.cpp
+++ b/src/MeoAssistant/RoguelikeTask.cpp
@@ -9,6 +9,7 @@
#include "RoguelikeControlTaskPlugin.h"
#include "RoguelikeCustomStartTaskPlugin.h"
#include "RoguelikeShoppingTaskPlugin.h"
+#include "RoguelikeResetTaskPlugin.h"
#include "Logger.hpp"
@@ -21,6 +22,7 @@ asst::RoguelikeTask::RoguelikeTask(const AsstCallback& callback, void* callback_
m_roguelike_task_ptr->regiseter_plugin();
m_roguelike_task_ptr->regiseter_plugin();
+ m_roguelike_task_ptr->regiseter_plugin();
m_roguelike_task_ptr->regiseter_plugin()->set_retry_times(0);
m_custom_start_task_ptr = m_roguelike_task_ptr->regiseter_plugin();
diff --git a/src/MeoAssistant/RuntimeStatus.h b/src/MeoAssistant/RuntimeStatus.h
index ffc01d45a9..6c5b2491cb 100644
--- a/src/MeoAssistant/RuntimeStatus.h
+++ b/src/MeoAssistant/RuntimeStatus.h
@@ -36,6 +36,8 @@ namespace asst
static inline const std::string RoguelikeCharElitePrefix = "RoguelikeElite-";
static inline const std::string RoguelikeCharLevelPrefix = "RoguelikeLevel-";
static inline const std::string RoguelikeCharRarityPrefix = "RoguelikeRarity-";
+ static inline const std::string RoguelikeCharOverview = "RoguelikeOverview";
+ static inline const std::string RoguelikeTraderNoLongerBuy = "RoguelikeNoLongerBuy";
private: