diff --git a/3rdparty/include/Arknights-Tile-Pos/TileCalc.hpp b/3rdparty/include/Arknights-Tile-Pos/TileCalc.hpp index 5f7587268d..6b688053d2 100644 --- a/3rdparty/include/Arknights-Tile-Pos/TileCalc.hpp +++ b/3rdparty/include/Arknights-Tile-Pos/TileCalc.hpp @@ -39,7 +39,7 @@ namespace Map { public: TileCalc(int width, int height, const std::string& dir); - bool run(const std::string& name, bool side, std::vector>& out_pos, std::vector>& out_tiles) const; + bool run(const std::string& code_or_name, bool side, std::vector>& out_pos, std::vector>& out_tiles) const; private: int width = 0; int height = 0; @@ -68,19 +68,13 @@ namespace Map Level::width = data.at("width").as_integer(); Level::view = data.at("view").as_integer(); for (const json::value& row : data.at("tiles").as_array()) { - std::vector tmp(Level::width); - auto iter = tmp.begin(); + std::vector tmp; + tmp.reserve(Level::width); for (const json::value& tile : row.as_array()) { - if (iter != tmp.end()) { - *iter = Tile{ - tile.at("heightType").as_integer(), - tile.at("buildableType").as_integer(), - tile.get("tileKey", std::string()) }; - ++iter; - } - else { - std::cerr << "Tiles json error" << std::endl; - } + tmp.emplace_back(Tile{ + tile.at("heightType").as_integer(), + tile.at("buildableType").as_integer(), + tile.get("tileKey", std::string()) }); } tiles.emplace_back(std::move(tmp)); } @@ -147,13 +141,13 @@ namespace Map return true; } - inline bool TileCalc::run(const std::string& name, bool side, std::vector>& out_pos, std::vector>& out_tiles) const + inline bool TileCalc::run(const std::string& code_or_name, bool side, std::vector>& out_pos, std::vector>& out_tiles) const { bool runned = false; double x = 0, y = 0, z = 0; for (const Map::Level& level : TileCalc::levels) { - if (/*level.code == code || */ - level.name == name) { + if (/*level.code == code_or_name || */ + level.name == code_or_name) { switch (level.view) { case 0: x = 0; diff --git a/resource/tasks.json b/resource/tasks.json index 904744f2cd..187710aedf 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -3136,6 +3136,10 @@ [ ".+兽小屋", "驯兽小屋" + ], + [ + "分.+不均", + "分赃不均" ] ], "roi": [ @@ -3481,14 +3485,7 @@ "algorithm": "justReturn", "next": [ "Roguelike1Start", - "Roguelike1StageTrader", - "Roguelike1StageEncounter", - "Roguelike1StageCambatDps", - "Roguelike1StageEmergencyDps", - "Roguelike1GetDrop1", - "Roguelike1GetDrop2", - "Roguelike1GetDrop3", - "Roguelike1GetDropLeave", + "Roguelike1DropsFlag", "Roguelike1StageEncounterFree", "Roguelike1StageEncounterLeave", "Roguelike1StageEncounterUnknown", @@ -3506,12 +3503,27 @@ ], "rearDelay": 500, "next": [ - "Roguelike1LastReward", "Roguelike1Recruit1" ] }, "Roguelike1LastReward": { + "Doc": "你的上一次探索突破了至少两层困难,这一次可以获得更多支援——热水壶", "action": "clickSelf", + "cache": false, + "roi": [ + 174, + 151, + 935, + 533 + ], + "next": [ + "Roguelike1LastRewardConfirm" + ] + }, + "Roguelike1LastReward2": { + "Doc": "你的上一次探索突破了至少两层困难,这一次可以获得更多支援——5源石锭", + "action": "clickSelf", + "cache": false, "roi": [ 174, 151, @@ -3532,7 +3544,7 @@ 533 ], "next": [ - "Roguelike1Recruit1" + "Roguelike1Team3" ] }, "Roguelike1Recruit1": { @@ -3556,6 +3568,8 @@ 200 ], "next": [ + "Roguelike1LastReward", + "Roguelike1LastReward2", "Roguelike1Team3" ] }, @@ -3595,7 +3609,8 @@ ], "next": [ "Roguelike1ChooseOper" - ] + ], + "rearDelay": 1000 }, "Roguelike1RecruitOther": { "action": "clickSelf", @@ -3609,21 +3624,73 @@ ], "next": [ "Roguelike1ChooseOper" - ] + ], + "rearDelay": 1000 }, "Roguelike1ChooseOper": { "algorithm": "OcrDetect", "action": "clickSelf", "cache": false, + "Doc": "所有肉鸽可能招募的干员,不在列表里的不会则被招募,可以手动修改,在前面的会优先招募", + "Doc2": "画面中如果既有低星又有高星,说明希望不够(高星是灰的不让选,但也被识别到了),所以尽量把低星的放前面,优先招募", "text": [ + "---三星备选干员---", + "芬", + "玫兰莎", + "香草", + "梓兰", + "芙蓉", + "安塞尔", + "预备干员", + "---近卫---", + "幽灵鲨", "煌", "银灰", "陈", "帕拉斯", "棘刺", - "梓兰", - "芙蓉", - "安塞尔" + "---先锋---", + "凛冬", + "德克萨斯", + "风笛", + "嵯峨", + "推进之王", + "---重装---", + "古米", + "蛇屠箱", + "临光", + "泥岩", + "塞雷娅", + "星熊", + "---狙击---", + "白金", + "能天使", + "假日威龙陈", + "黑", + "---术士---", + "阿米娅", + "天火", + "艾雅法拉", + "异客", + "---治疗---", + "白面鸮", + "赫默", + "凯尔希", + "闪灵", + "夜莺", + "---辅助---", + "梅尔", + "巫恋", + "初雪", + "真理", + "安洁莉娜", + "铃兰", + "令", + "麦哲伦", + "---特种---", + "孑", + "水月", + "狮蝎" ], "roi": [ 560, @@ -3631,6 +3698,16 @@ 666, 614 ], + "ocrReplace": [ + [ + "白面.+", + "白面鸮" + ], + [ + "^子$", + "孑" + ] + ], "next": [ "Roguelike1ChooseOperConfirm" ] @@ -3658,6 +3735,7 @@ ], "next": [ "Roguelike1RecruitSkip", + "Roguelike1DropsFlag", "Roguelike1RecruitWithoutButton" ] }, @@ -3674,6 +3752,7 @@ "next": [ "Roguelike1RecruitOther", "Roguelike1EnterAfterRecruit", + "Roguelike1DropsFlag", "Roguelike1RecruitWithoutButton" ] }, @@ -3689,6 +3768,7 @@ "next": [ "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ] @@ -3707,6 +3787,7 @@ "Roguelike1StageTraderEnter", "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ] @@ -3811,6 +3892,7 @@ "next": [ "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ] @@ -3829,6 +3911,26 @@ "Roguelike1StageEncounterEnter", "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", + "Roguelike1StageCambatDps", + "Roguelike1StageEmergencyDps" + ] + }, + "Roguelike1StageBoons": { + "Doc": "古堡馈赠(随机奖励)", + "action": "clickSelf", + "cache": false, + "roi": [ + 0, + 53, + 1280, + 554 + ], + "next": [ + "Roguelike1StageEncounterEnter", + "Roguelike1StageTrader", + "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ] @@ -3904,6 +4006,7 @@ ], "rearDelay": 1000, "next": [ + "Roguelike1ChooseOper", "Roguelike1StageEncounterGiveUpRecruit", "Roguelike1ClickToDrops" ] @@ -3930,6 +4033,7 @@ 171 ], "next": [ + "Roguelike1DropsFlag", "Roguelike1ClickToDrops" ] }, @@ -3964,6 +4068,7 @@ "Roguelike1StageEmergencyDpsEnter", "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ], @@ -3979,7 +4084,8 @@ ], "next": [ "Roguelike1QuickFormation" - ] + ], + "rearDelay": 2000 }, "Roguelike1StageEmergencyDps": { "Doc": "紧急作战", @@ -3996,6 +4102,7 @@ "Roguelike1StageEmergencyDpsEnter", "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ], @@ -4116,6 +4223,7 @@ "Roguelike1DropsFlag", "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps", "Roguelike1ClickToDrops" @@ -4129,12 +4237,15 @@ 119 ], "next": [ + "Roguelike1GetDropCompleted", "Roguelike1GetDrop1", "Roguelike1GetDrop2", "Roguelike1GetDrop3", + "Roguelike1GetDropRecruit", "Roguelike1GetDropLeave", "Roguelike1StageTrader", "Roguelike1StageEncounter", + "Roguelike1StageBoons", "Roguelike1StageCambatDps", "Roguelike1StageEmergencyDps" ] @@ -4150,8 +4261,7 @@ 157 ], "next": [ - "Roguelike1DropsFlag", - "Roguelike1GetDropCompleted" + "Roguelike1DropsFlag" ] }, "Roguelike1GetDrop2": { @@ -4166,7 +4276,6 @@ ], "next": [ "Roguelike1DropsFlag", - "Roguelike1GetDropCompleted", "Roguelike1ClickToDrops" ] }, @@ -4182,10 +4291,25 @@ ], "next": [ "Roguelike1DropsFlag", - "Roguelike1GetDropCompleted", "Roguelike1ClickToDrops" ] }, + "Roguelike1GetDropRecruit": { + "Doc": "招募券,白色的“招募”按钮", + "action": "clickSelf", + "cache": false, + "roi": [ + 0, + 471, + 1280, + 157 + ], + "rearDelay": 1000, + "next": [ + "Roguelike1ChooseOper", + "Roguelike1StageEncounterGiveUpRecruit" + ] + }, "Roguelike1GetDropCompleted": { "action": "clickRect", "specificRect": [ diff --git a/resource/template/Roguelike1GetDropRecruit.png b/resource/template/Roguelike1GetDropRecruit.png new file mode 100644 index 0000000000..d9284577a6 Binary files /dev/null and b/resource/template/Roguelike1GetDropRecruit.png differ diff --git a/resource/template/Roguelike1LastReward2.png b/resource/template/Roguelike1LastReward2.png new file mode 100644 index 0000000000..8b84ea6b73 Binary files /dev/null and b/resource/template/Roguelike1LastReward2.png differ diff --git a/resource/template/Roguelike1StageBoons.png b/resource/template/Roguelike1StageBoons.png new file mode 100644 index 0000000000..3b96cf68de Binary files /dev/null and b/resource/template/Roguelike1StageBoons.png differ diff --git a/src/MeoAssistant/AsstDef.h b/src/MeoAssistant/AsstDef.h index 3d91f0af57..777c0f02d0 100644 --- a/src/MeoAssistant/AsstDef.h +++ b/src/MeoAssistant/AsstDef.h @@ -115,6 +115,10 @@ namespace asst { return text == rhs.text && rect == rhs.rect; } + bool operator==(const std::string& rhs) const noexcept + { + return text == rhs; + } double score = 0.0; Rect rect; diff --git a/src/MeoAssistant/HashImageAnalyzer.cpp b/src/MeoAssistant/HashImageAnalyzer.cpp index 7140491522..1a06ad1239 100644 --- a/src/MeoAssistant/HashImageAnalyzer.cpp +++ b/src/MeoAssistant/HashImageAnalyzer.cpp @@ -38,7 +38,7 @@ bool asst::HashImageAnalyzer::analyze() std::string cur_min_dist_name; for (auto&& [name, templ] : m_hash_templates) { int hm = hamming(hash_result, templ); - Log.trace(name, "dist:", hm); + //Log.debug(name, "dist:", hm); if (hm < min_dist) { cur_min_dist_name = name; min_dist = hm; diff --git a/src/MeoAssistant/OcrImageAnalyzer.cpp b/src/MeoAssistant/OcrImageAnalyzer.cpp index 6985810e01..0818ef69d1 100644 --- a/src/MeoAssistant/OcrImageAnalyzer.cpp +++ b/src/MeoAssistant/OcrImageAnalyzer.cpp @@ -1,6 +1,7 @@ #include "OcrImageAnalyzer.h" #include +#include #include "Logger.hpp" #include "Resource.h" @@ -32,7 +33,11 @@ bool asst::OcrImageAnalyzer::analyze() else { TextRectProc required_search = [&](TextRect& tr) -> bool { auto is_sub = [&tr](const std::string& str) -> bool { - return tr.text.find(str) != std::string::npos; + if (tr.text.find(str) == std::string::npos) { + return false; + } + tr.text = str; + return true; }; return std::find_if(m_required.cbegin(), m_required.cend(), is_sub) != m_required.cend(); }; @@ -131,3 +136,20 @@ void asst::OcrImageAnalyzer::sort_result() } ); } + +void asst::OcrImageAnalyzer::sort_result_by_required() +{ + if (m_required.empty()) { + return; + } + + std::unordered_map m_req_cache; + for (size_t i = 0; i != m_required.size(); ++i) { + m_req_cache.emplace(m_required.at(i), i + 1); + } + + std::sort(m_ocr_result.begin(), m_ocr_result.end(), + [&m_req_cache](const auto& lhs, const auto& rhs) -> bool { + return m_req_cache[lhs.text] < m_req_cache[rhs.text]; + }); +} diff --git a/src/MeoAssistant/OcrImageAnalyzer.h b/src/MeoAssistant/OcrImageAnalyzer.h index ceeb9e3433..55b3e2f876 100644 --- a/src/MeoAssistant/OcrImageAnalyzer.h +++ b/src/MeoAssistant/OcrImageAnalyzer.h @@ -17,7 +17,8 @@ namespace asst virtual bool analyze() override; - void sort_result(); // 按位置排序,左上角的排在前面 + void sort_result(); // 按位置排序,左上角的排在前面 + void sort_result_by_required(); // 按传入的需求数组排序,传入的在前面结果接在前面 void set_required(std::vector required, bool full_match = false) noexcept; void set_replace(std::unordered_map replace) noexcept; diff --git a/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp b/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp index c04ad37309..4230644a7a 100644 --- a/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp +++ b/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp @@ -72,6 +72,7 @@ bool asst::ProcessTaskImageAnalyzer::ocr_analyze(std::shared_ptr task_ bool ret = m_ocr_analyzer->analyze(); if (ret) { + m_ocr_analyzer->sort_result_by_required(); const auto& ocr_result = m_ocr_analyzer->get_result(); auto& res = ocr_result.front(); m_result = ocr_task_ptr; diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp index a04bb64606..b445bfcdee 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp @@ -153,8 +153,19 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() case Role::Special: case Role::Drone: default: - loc = Loc::All; - break; + // 特种和无人机,有的只能放地面,有的又只能放高台,不好判断 + // 笨办法,都试试,总有一次能成的 + { + static Loc static_loc = Loc::Melee; + loc = static_loc; + if (static_loc == Loc::Melee) { + static_loc = Loc::Ranged; + } + else { + static_loc = Loc::Melee; + } + } + break; } Point placed_point = get_placed(loc); diff --git a/src/MeoAssistant/TilePack.cpp b/src/MeoAssistant/TilePack.cpp index 48208bd71f..de9af12bee 100644 --- a/src/MeoAssistant/TilePack.cpp +++ b/src/MeoAssistant/TilePack.cpp @@ -68,7 +68,8 @@ std::vector asst::TilePack::calc(const std::string & s static_cast(tile.buildableType), static_cast(tile.heightType), key, - Point(static_cast(cv_p.x), static_cast(cv_p.y)) + Point(static_cast(cv_p.x), static_cast(cv_p.y)), + Point(static_cast(x), static_cast(y)) }); } } diff --git a/src/MeoAssistant/TilePack.h b/src/MeoAssistant/TilePack.h index 4bb5059b19..205cde3b76 100644 --- a/src/MeoAssistant/TilePack.h +++ b/src/MeoAssistant/TilePack.h @@ -44,7 +44,8 @@ namespace asst BuildableType buildable = BuildableType::Invaild; HeightType height = HeightType::Invaild; TileKey key = TileKey::Invaild; - Point pos; + Point pos; // 像素坐标 + Point loc; // 格子坐标 }; public: using AbstractResource::AbstractResource; diff --git a/src/MeoAssistant/Version.h b/src/MeoAssistant/Version.h index 2022abf193..4700a90b01 100644 --- a/src/MeoAssistant/Version.h +++ b/src/MeoAssistant/Version.h @@ -2,5 +2,5 @@ namespace asst { - constexpr static const char* Version = "v2.8.0"; + constexpr static const char* Version = "v2.9.0-beta"; }