Compare commits

...

21 Commits

Author SHA1 Message Date
MistEO
dd556817ea update version id 2021-07-21 20:36:29 +08:00
MistEO
c393da2046 Merge pull request #3 from MistEO/feature/new_algorithm
Feature/new algorithm
2021-07-21 20:17:11 +08:00
MistEO
5657af6d94 update config and something 2021-07-21 20:16:33 +08:00
MistEO
f35ef18bd2 add log 2021-07-21 20:16:02 +08:00
MistEO
0fef8e2174 merge "Updater interface modified" 2021-07-21 02:05:23 +08:00
MistEO
ee3afb440e modified the interface of Updater, because VS2019 's O2 optimzation is not friendly to std::optional 2021-07-21 01:43:58 +08:00
MistEO
952861c1e5 update icon and window title 2021-07-20 23:51:47 +08:00
MistEO
dab705a3de fixed bug: process cannot exit 2021-07-20 23:37:27 +08:00
MistEO
17f8353a97 fixed bug: process cannot exit 2021-07-20 23:36:57 +08:00
MistEO
53a1297842 update task sleep logic 2021-07-20 23:29:01 +08:00
MistEO
e589a7498c update identify algorithm 2021-07-20 23:17:10 +08:00
MistEO
ca412965ca add icon for GUI 2021-07-20 21:50:26 +08:00
MistEO
adfed6d276 update release body 2021-07-20 00:50:34 +08:00
MistEO
6fddf69e67 add function of check version update 2021-07-20 00:12:00 +08:00
MistEO
fb3cbb0b7a add set max times function 2021-07-19 21:22:35 +08:00
MistEO
a348139df5 update configer 2021-07-18 23:22:47 +08:00
MistEO
08db7f008d Merge branch 'master' of https://github.com/MistEO/MeoAssistance 2021-07-18 17:43:25 +08:00
MistEO
d66f178aec update gui, add use stone label 2021-07-18 17:43:16 +08:00
MistEO
d51882fd1c Update README.md 2021-07-18 17:29:09 +08:00
MistEO
c7b80b4603 support to MuMu (not MuMuAsst) 2021-07-18 15:19:15 +08:00
MistEO
1a0add784d try to supoort MuMu 2021-07-18 02:40:57 +08:00
33 changed files with 743 additions and 121 deletions

View File

@@ -24,6 +24,7 @@
<ClInclude Include="include\AsstDef.h" />
<ClInclude Include="include\Configer.h" />
<ClInclude Include="include\Identify.h" />
<ClInclude Include="include\Updater.h" />
<ClInclude Include="include\WinMacro.h" />
</ItemGroup>
<ItemGroup>
@@ -31,6 +32,7 @@
<ClCompile Include="src\AsstCaller.cpp" />
<ClCompile Include="src\Configer.cpp" />
<ClCompile Include="src\Identify.cpp" />
<ClCompile Include="src\Updater.cpp" />
<ClCompile Include="src\WinMacro.cpp" />
</ItemGroup>
<ItemGroup>
@@ -145,7 +147,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opencv_world452d.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>opencv_world452d.lib;libmeojson.lib;WinInet.Lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
</Link>
@@ -177,7 +179,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>opencv_core452.lib;opencv_imgcodecs452.lib;opencv_imgproc452.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>opencv_core452.lib;opencv_imgcodecs452.lib;opencv_imgproc452.lib;WinInet.Lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
</Link>
@@ -197,7 +199,7 @@
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties _1_1_4resource_4config_1json__JsonSchema="https://beaujs.com/schema.json" />
<UserProperties _1_1_4resource_4config_1json__JsonSchema="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -33,6 +33,9 @@
<ClInclude Include="include\AsstCaller.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Updater.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Configer.cpp">
@@ -50,6 +53,9 @@
<ClCompile Include="src\AsstCaller.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Updater.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resource\config.json">

View File

@@ -22,10 +22,10 @@ namespace asst {
std::optional<std::string> setSimulator(const std::string & simulator_name = std::string());
void start(const std::string & task);
void stop();
void stop(bool block = true);
bool setParam(const std::string& type, const std::string& param, const std::string& value);
std::optional<std::string> getParam(const std::string& type, const std::string& param);
private:
static void workingProc(Assistance* pThis);

View File

@@ -12,6 +12,8 @@ extern __declspec(dllexport) bool AsstCatchSimulator(asst::Assistance* p_asst);
extern __declspec(dllexport) void AsstStart(asst::Assistance* p_asst, const char* task);
extern __declspec(dllexport) void AsstStop(asst::Assistance* p_asst);
extern __declspec(dllexport) bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value);
extern __declspec(dllexport) bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size);
extern __declspec(dllexport) bool CheckVersionUpdate(char * tag_buffer, int tag_bufsize, char * html_url_buffer, int html_bufsize, char * body_buffer, int body_bufsize);
#ifdef __cplusplus
}

View File

@@ -1,13 +1,20 @@
#pragma once
#include <mutex>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <process.h>
#include <Windows.h>
namespace asst {
const static std::string Version = "release.beta.01";
/************ Type ************/
enum class HandleType
{
Window = 1,
@@ -44,6 +51,8 @@ namespace asst {
int height = 0;
};
/************ Static Function ************/
static std::string GetCurrentDir()
{
static std::string cur_dir;
@@ -61,6 +70,20 @@ namespace asst {
return res_dir;
}
static std::string replace_all_distinct(const std::string& src, const std::string& old_value, const std::string& new_value)
{
std::string str = src;
for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) {
if ((pos = str.find(old_value, pos)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else
break;
}
return str;
}
/************ Print and Log Trace ************/
inline void StreamArgs(std::ostream& os)
{
os << std::endl;
@@ -77,7 +100,7 @@ namespace asst {
static std::mutex trace_mutex;
std::unique_lock<std::mutex> trace_lock(trace_mutex);
#ifdef _DEBUG
auto & out_stream = std::cout;
auto& out_stream = std::cout;
#else
std::ofstream out_stream(GetCurrentDir() + "asst.log", std::ios::out | std::ios::app);
#endif
@@ -110,4 +133,26 @@ namespace asst {
{
DebugPrint("ERR", std::forward<Args>(args)...);
}
class DebugTraceFuncAux {
public:
DebugTraceFuncAux(const std::string& func_name)
: m_func_name(func_name),
m_start_time(std::chrono::system_clock::now())
{
DebugTrace(m_func_name, " | enter");
}
~DebugTraceFuncAux()
{
auto duration = std::chrono::system_clock::now() - m_start_time;
DebugTrace(m_func_name, " | leave,",
std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(), "ms");
}
private:
std::string m_func_name;
std::chrono::time_point<std::chrono::system_clock> m_start_time;
};
#define DebugTraceFunction DebugTraceFuncAux _func_aux(__FUNCTION__)
}

View File

@@ -3,6 +3,8 @@
#include <string>
#include <unordered_map>
#include <vector>
#include <optional>
#include "AsstDef.h"
namespace asst {
@@ -10,14 +12,21 @@ namespace asst {
std::string className;
std::string windowName;
};
struct AdbCmd {
std::string path;
std::string connect;
std::string click;
};
struct SimulatorInfo {
std::vector<HandleInfo> window;
std::vector<HandleInfo> view;
std::vector<HandleInfo> control;
bool is_adb = false;
AdbCmd adb;
int width = 0;
int height = 0;
int xOffset = 0;
int yOffset = 0;
int x_offset = 0;
int y_offset = 0;
};
enum class TaskType {
@@ -31,10 +40,12 @@ namespace asst {
struct TaskInfo {
std::string filename;
double threshold = 0;
double cache_threshold = 0;
TaskType type;
std::vector<std::string> next;
int exec_times = 0;
int max_times = INT_MAX;
std::vector<std::string> exceeded_next;
asst::Rect specific_area;
int pre_delay = 0;
int rear_delay = 0;
@@ -58,6 +69,12 @@ namespace asst {
static std::unordered_map<std::string, SimulatorInfo> m_handles;
static bool setParam(const std::string& type, const std::string& param, const std::string& value);
static std::optional<std::string> getParam(const std::string& type, const std::string& param);
static void clearExecTimes();
constexpr static double DefaultThreshold = 0.9;
constexpr static double DefaultCacheThreshold = 0.9;
private:
Configer() = default;

View File

@@ -0,0 +1,35 @@
#pragma once
#include <string>
#include <optional>
namespace asst {
struct __declspec(dllexport) VersionInfo {
std::string tag_name;
std::string html_url;
std::string down_url;
std::string author_name;
std::string created_time;
std::string body;
};
class __declspec(dllexport) Updater
{
static const std::string GithubReleaseLastestApiUrl;
static const std::string GithubReleaseApiUrl;
public:
~Updater() = default;
static Updater& instance();
bool has_new_version();
const VersionInfo & get_version_info() const noexcept;
private:
Updater() = default;
std::optional<std::string> request_github_api();
bool m_has_new_version = false;
VersionInfo m_lastest_version;
};
}

View File

@@ -30,10 +30,12 @@ namespace asst {
const std::string m_simulator_name;
const HandleType m_handle_type;
HWND m_handle = NULL;
bool m_is_adb = false;
std::string m_click_cmd;
std::minstd_rand m_rand_engine;
int m_width = 0;
int m_height = 0;
int m_xOffset = 0;
int m_yOffset = 0;
int m_x_offset = 0;
int m_y_offset = 0;
};
}

View File

@@ -8,6 +8,8 @@ using namespace asst;
Assistance::Assistance()
{
DebugTraceFunction;
Configer::reload();
m_pIder = std::make_shared<Identify>();
@@ -23,6 +25,8 @@ Assistance::Assistance()
Assistance::~Assistance()
{
DebugTraceFunction;
if (m_pWindow != nullptr) {
m_pWindow->showWindow();
}
@@ -38,6 +42,8 @@ Assistance::~Assistance()
std::optional<std::string> Assistance::setSimulator(const std::string& simulator_name)
{
DebugTraceFunction;
stop();
auto create_handles = [&](const std::string& name) -> bool {
@@ -65,7 +71,7 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
else {
ret = create_handles(simulator_name);
}
if (ret && m_pWindow->resizeWindow()) {
if (ret && m_pWindow->showWindow() && m_pWindow->resizeWindow()) {
m_inited = true;
return cor_name;
}
@@ -77,11 +83,15 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
void Assistance::start(const std::string& task)
{
DebugTraceFunction;
if (m_thread_running || !m_inited) {
return;
}
std::unique_lock<std::mutex> lock(m_mutex);
Configer::clearExecTimes();
m_pIder->clear_cache();
m_next_tasks.clear();
m_next_tasks.emplace_back(task);
@@ -89,10 +99,15 @@ void Assistance::start(const std::string& task)
m_condvar.notify_one();
}
void Assistance::stop()
void Assistance::stop(bool block)
{
std::unique_lock<std::mutex> lock(m_mutex);
DebugTraceFunction;
std::unique_lock<std::mutex> lock;
if (block) { // Íⲿµ÷ÓÃ
lock = std::unique_lock<std::mutex>(m_mutex);
Configer::clearExecTimes();
}
m_thread_running = false;
m_next_tasks.clear();
m_pIder->clear_cache();
@@ -100,11 +115,22 @@ void Assistance::stop()
bool Assistance::setParam(const std::string& type, const std::string& param, const std::string& value)
{
DebugTraceFunction;
return Configer::setParam(type, param, value);
}
std::optional<std::string> Assistance::getParam(const std::string& type, const std::string& param)
{
DebugTraceFunction;
return Configer::getParam(type, param);
}
void Assistance::workingProc(Assistance* pThis)
{
DebugTraceFunction;
while (!pThis->m_thread_exit) {
std::unique_lock<std::mutex> lock(pThis->m_mutex);
if (pThis->m_thread_running) {
@@ -113,12 +139,13 @@ void Assistance::workingProc(Assistance* pThis)
std::string matched_task;
Rect matched_rect;
for (auto&& task_name : pThis->m_next_tasks) {
double threshold = Configer::m_tasks[task_name].threshold;
auto&& task = Configer::m_tasks[task_name];
double threshold = task.threshold;
auto&& [algorithm, value, rect] = pThis->m_pIder->findImage(curImg, task_name, threshold);
DebugTrace(task_name, "Type:", algorithm, "Value:", value);
if (algorithm == 0 ||
(algorithm == 1 && value >= threshold)
|| (algorithm == 2 && value >= 0.9998)) {
|| (algorithm == 2 && value >= task.cache_threshold)) {
matched_task = task_name;
matched_rect = rect;
break;
@@ -126,49 +153,59 @@ void Assistance::workingProc(Assistance* pThis)
}
if (!matched_task.empty()) {
auto && task = Configer::m_tasks[matched_task];
DebugTraceInfo("Matched:", matched_task, "Type:", static_cast<int>(task.type));
auto&& task = Configer::m_tasks[matched_task];
DebugTraceInfo("***Matched***", matched_task, "Type:", static_cast<int>(task.type));
if (task.pre_delay > 0) {
DebugTrace("PreDelay", task.pre_delay);
std::this_thread::sleep_for(std::chrono::milliseconds(task.pre_delay));
}
switch (task.type) {
case TaskType::ClickRect:
matched_rect = task.specific_area;
case TaskType::ClickSelf:
if (task.max_times != INT_MAX) {
DebugTrace("CurTimes:", task.exec_times, "MaxTimes:", task.max_times);
}
if (task.exec_times >= task.max_times) {
DebugTraceInfo("Reached limit, Stop.");
pThis->m_thread_running = false;
pThis->m_next_tasks.clear();
// std::this_thread::sleep_for(std::chrono::milliseconds(task.pre_delay));
auto cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(task.pre_delay),
[&]() -> bool { return !pThis->m_thread_running; });
if (cv_ret == true) {
continue;
}
pThis->m_pCtrl->clickRange(matched_rect);
++task.exec_times;
break;
case TaskType::ClickRand:
pThis->m_pCtrl->clickRange(pThis->m_pCtrl->getWindowRect());
break;
case TaskType::DoNothing:
break;
case TaskType::Stop:
DebugTrace("TaskType is Stop");
pThis->m_thread_running = false;
pThis->m_next_tasks.clear();
continue;
break;
default:
DebugTraceError("Unknown option type:", static_cast<int>(task.type));
break;
}
if (task.rear_delay > 0) {
DebugTrace("RearDelay", task.rear_delay);
std::this_thread::sleep_for(std::chrono::milliseconds(task.rear_delay));
}
pThis->m_next_tasks = Configer::m_tasks[matched_task].next;
if (task.max_times != INT_MAX) {
DebugTrace("CurTimes:", task.exec_times, "MaxTimes:", task.max_times);
}
if (task.exec_times < task.max_times) {
switch (task.type) {
case TaskType::ClickRect:
matched_rect = task.specific_area;
case TaskType::ClickSelf:
pThis->m_pCtrl->clickRange(matched_rect);
break;
case TaskType::ClickRand:
pThis->m_pCtrl->clickRange(pThis->m_pCtrl->getWindowRect());
break;
case TaskType::DoNothing:
break;
case TaskType::Stop:
DebugTrace("TaskType is Stop");
pThis->stop(false);
continue;
break;
default:
DebugTraceError("Unknown option type:", static_cast<int>(task.type));
break;
}
++task.exec_times;
if (task.rear_delay > 0) {
DebugTrace("RearDelay", task.rear_delay);
// std::this_thread::sleep_for(std::chrono::milliseconds(task.rear_delay));
auto cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(task.rear_delay),
[&]() -> bool { return !pThis->m_thread_running; });
if (cv_ret == true) {
continue;
}
}
pThis->m_next_tasks = Configer::m_tasks[matched_task].next;
}
else {
DebugTraceInfo("Reached limit");
pThis->m_next_tasks = Configer::m_tasks[matched_task].exceeded_next;
}
std::string nexts_str;
for (auto&& name : pThis->m_next_tasks) {
nexts_str += name + ",";
@@ -178,7 +215,9 @@ void Assistance::workingProc(Assistance* pThis)
}
DebugTrace("Next:", nexts_str);
}
pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(Configer::m_options.delayFixedTime));
pThis->m_condvar.wait_for(lock,
std::chrono::milliseconds(Configer::m_options.delayFixedTime),
[&]() -> bool { return !pThis->m_thread_running; });
}
else {
pThis->m_condvar.wait(lock);

View File

@@ -1,5 +1,7 @@
#include "AsstCaller.h"
#include "Updater.h"
#include <string.h>
asst::Assistance* CreateAsst()
{
@@ -54,5 +56,31 @@ bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param,
return false;
}
p_asst->setParam(type, param, value);
return p_asst->setParam(type, param, value);
}
bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size)
{
if (p_asst == NULL) {
return false;
}
auto ret = p_asst->getParam(type, param);
if (!ret) {
return false;
}
strcpy_s(buffer, buffer_size, ret.value().c_str());
return true;
}
bool CheckVersionUpdate(char* tag_buffer, int tag_bufsize, char* html_url_buffer, int html_bufsize, char* body_buffer, int body_bufsize)
{
bool ret = asst::Updater::instance().has_new_version();
if (!ret) {
return false;
}
auto && info = asst::Updater::instance().get_version_info();
strcpy_s(tag_buffer, tag_bufsize, info.tag_name.c_str());
strcpy_s(html_url_buffer, html_bufsize, info.html_url.c_str());
strcpy_s(body_buffer, body_bufsize, info.body.c_str());
return true;
}

View File

@@ -47,7 +47,18 @@ bool Configer::reload()
for (auto&& [name, task_json] : tasks_obj) {
TaskInfo task_info;
task_info.filename = task_json["filename"].as_string();
task_info.threshold = task_json["threshold"].as_double();
if (task_json.exist("threshold")) {
task_info.threshold = task_json["threshold"].as_double();
}
else {
task_info.threshold = DefaultThreshold;
}
if (task_json.exist("cache_threshold")) {
task_info.cache_threshold = task_json["cache_threshold"].as_double();
}
else {
task_info.cache_threshold = DefaultCacheThreshold;
}
std::string type = task_json["type"].as_string();
std::transform(type.begin(), type.end(), type.begin(), std::tolower);
if (type == "clickself") {
@@ -75,13 +86,22 @@ bool Configer::reload()
DebugTraceError("Task:", name, "error:", type);
return false;
}
if (task_json.as_object().exist("maxTimes")) {
if (task_json.exist("maxTimes")) {
task_info.max_times = task_json["maxTimes"].as_integer();
}
if (task_json.as_object().exist("preDelay")) {
if (task_json.exist("exceededNext")) {
auto next_arr = task_json["exceededNext"].as_array();
for (auto&& name : next_arr) {
task_info.exceeded_next.emplace_back(name.as_string());
}
}
else {
task_info.exceeded_next.emplace_back("Stop");
}
if (task_json.exist("preDelay")) {
task_info.pre_delay = task_json["preDelay"].as_integer();
}
if (task_json.as_object().exist("rearDelay")) {
if (task_json.exist("rearDelay")) {
task_info.rear_delay = task_json["rearDelay"].as_integer();
}
@@ -119,10 +139,17 @@ bool Configer::reload()
handle_info.windowName = info["window"].as_string();
simulator_info.control.emplace_back(handle_info);
}
if (simulator_json.exist("adbControl")) {
simulator_info.is_adb = true;
// meojson的bug暂时没空修先转个字符串
simulator_info.adb.path = replace_all_distinct(simulator_json["adbControl"]["path"].as_string(), "\\\\", "\\");
simulator_info.adb.connect = simulator_json["adbControl"]["connect"].as_string();
simulator_info.adb.click = simulator_json["adbControl"]["click"].as_string();
}
simulator_info.width = simulator_json["width"].as_integer();
simulator_info.height = simulator_json["height"].as_integer();
simulator_info.xOffset = simulator_json["xOffset"].as_integer();
simulator_info.yOffset = simulator_json["yOffset"].as_integer();
simulator_info.x_offset = simulator_json["xOffset"].as_integer();
simulator_info.y_offset = simulator_json["yOffset"].as_integer();
m_handles.emplace(name, simulator_info);
}
@@ -171,4 +198,19 @@ bool Configer::setParam(const std::string& type, const std::string& param, const
m_tasks[param].max_times = std::stoi(value);
}
return true;
}
std::optional<std::string> Configer::getParam(const std::string& type, const std::string& param)
{
if (type == "task.execTimes" && m_tasks.find(param) != m_tasks.cend()) {
return std::to_string(m_tasks.at(param).exec_times);
}
return std::nullopt;
}
void Configer::clearExecTimes()
{
for (auto&& t : m_tasks) {
t.second.exec_times = 0;
}
}

View File

@@ -48,7 +48,8 @@ Mat Identify::image2Hist(const cv::Mat& src)
double Identify::imageHistComp(const cv::Mat& src, const cv::MatND& hist)
{
return compareHist(image2Hist(src), hist, CV_COMP_CORREL);
// keep the interface return value unchanged
return 1 - compareHist(image2Hist(src), hist, CV_COMP_BHATTACHARYYA);
}
std::pair<double, cv::Point> Identify::findImage(const cv::Mat& image, const cv::Mat& templ)
@@ -59,7 +60,7 @@ std::pair<double, cv::Point> Identify::findImage(const cv::Mat& image, const cv:
cvtColor(templ, templ_hsv, COLOR_BGR2HSV);
Mat matched;
matchTemplate(image_hsv, templ_hsv, matched, cv::TM_CCORR_NORMED);
matchTemplate(image_hsv, templ_hsv, matched, cv::TM_CCOEFF_NORMED);
double minVal = 0, maxVal = 0;
cv::Point minLoc, maxLoc;

View File

@@ -0,0 +1,98 @@
#include "Updater.h"
#include <stdio.h>
#include <Windows.h>
#include <WinInet.h>
#include "json.h"
#include "AsstDef.h"
using namespace asst;
const std::string Updater::GithubReleaseLastestApiUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
const std::string Updater::GithubReleaseApiUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
Updater& Updater::instance()
{
static Updater unique_instance;
return unique_instance;
}
bool Updater::has_new_version()
{
auto req_ret = request_github_api();
if (!req_ret) {
DebugTraceInfo("Requeset Error");
return false;
}
auto parse_ret = json::parser::parse(req_ret.value());
if (!parse_ret) {
DebugTraceInfo("Parse Error");
return false;
}
json::value root = std::move(parse_ret).value();
try {
m_lastest_version.tag_name = root["tag_name"].as_string();
m_lastest_version.html_url = root["html_url"].as_string();
m_lastest_version.author_name = root["author"]["login"].as_string();
m_lastest_version.created_time = root["created_at"].as_string();
m_lastest_version.body = root["body"].as_string();
auto assets = root["assets"].as_array();
if (assets.size() == 1) {
m_lastest_version.down_url = assets[0]["browser_download_url"].as_string();
}
}
catch (json::exception& exp) {
DebugTraceError("Json Error", exp.what());
return false;
}
if (m_lastest_version.tag_name > Version) {
m_has_new_version = true;
return true;
}
else {
return false;
}
}
const VersionInfo & Updater::get_version_info() const noexcept
{
if (!m_has_new_version) {
return VersionInfo();
}
return m_lastest_version;
}
std::optional<std::string> Updater::request_github_api()
{
HINTERNET h_session = ::InternetOpenA("GithubRelease", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (h_session == NULL) {
return std::nullopt;
}
HINTERNET h_http = ::InternetOpenUrlA(h_session, GithubReleaseLastestApiUrl.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (h_http == NULL) {
return std::nullopt;
}
std::string response;
size_t buff_size = 4096;
char *buffer = new char[buff_size];
DWORD number = 1;
while (number > 0) {
memset(buffer, 0, buff_size);
InternetReadFile(h_http, buffer, buff_size, &number);
if (number != 0) {
response += std::string(buffer, number);
}
}
delete[] buffer;
buffer = NULL;
InternetCloseHandle(h_http);
h_http = NULL;
InternetCloseHandle(h_session);
h_session = NULL;
return response;
}

View File

@@ -40,8 +40,9 @@ bool WinMacro::findHandle()
handle_vec = info.view;
break;
case HandleType::Control:
m_xOffset = info.xOffset;
m_yOffset = info.yOffset;
m_is_adb = info.is_adb;
m_x_offset = info.x_offset;
m_y_offset = info.y_offset;
handle_vec = info.control;
break;
default:
@@ -77,7 +78,29 @@ bool WinMacro::findHandle()
window_wbuff = NULL;
}
}
if (m_is_adb && m_handle != NULL) {
DWORD pid = 0;
::GetWindowThreadProcessId(m_handle, &pid);
HANDLE handle = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
LPSTR path_buff = new CHAR[MAX_PATH];
memset(path_buff, 0, MAX_PATH);
DWORD buff_size = MAX_PATH;
QueryFullProcessImageNameA(handle, 0, path_buff, &buff_size);
std::string adb_dir = path_buff;
if (path_buff != NULL) {
delete[] path_buff;
path_buff = NULL;
}
size_t pos = adb_dir.find_last_of('\\') + 1;
adb_dir = adb_dir.substr(0, pos);
adb_dir = '"' + replace_all_distinct(info.adb.path, "[EmulatorPath]", adb_dir) + '"';
std::string connect_cmd = adb_dir + info.adb.connect;
int ret = system(connect_cmd.c_str());
DebugTrace("Call", connect_cmd, "—— ret", ret);
m_click_cmd = adb_dir + info.adb.click;
}
DebugTrace("Handle:", m_handle, "Name:", m_simulator_name, "Type:", static_cast<int>(m_handle_type));
if (m_handle != NULL) {
@@ -111,7 +134,7 @@ bool WinMacro::showWindow()
return false;
}
return ::ShowWindow(m_handle, SW_SHOW);
return ::ShowWindow(m_handle, SW_RESTORE);
}
bool WinMacro::hideWindow()
@@ -163,17 +186,29 @@ bool WinMacro::click(const Point& p)
return false;
}
int x = (p.x + m_xOffset) / getScreenScale();
int y = (p.y + m_yOffset) / getScreenScale();
DebugTrace("click, raw:", p.x, p.y, "cor:", x, y);
LPARAM lparam = MAKELPARAM(x, y);
if (m_is_adb) {
int x = (p.x + m_x_offset);
int y = (p.y + m_y_offset);
std::string cur_cmd = replace_all_distinct(m_click_cmd, "[x]", std::to_string(x));
cur_cmd = replace_all_distinct(cur_cmd, "[y]", std::to_string(y));
int ret = system(cur_cmd.c_str());
DebugTrace("Call", cur_cmd, "—— ret", ret);
return !ret;
}
else {
int x = (p.x + m_x_offset) / getScreenScale();
int y = (p.y + m_y_offset) / getScreenScale();
DebugTrace("Click, raw:", p.x, p.y, "cor:", x, y);
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
LPARAM lparam = MAKELPARAM(x, y);
return true;
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
return true;
}
}
bool WinMacro::clickRange(const Rect& rect)
@@ -242,12 +277,12 @@ cv::Mat WinMacro::getImage(const Rect& rect)
DeleteDC(memDC);
ReleaseDC(m_handle, pDC);
/*
#ifdef _DEBUG
std::string filename = GetCurrentDir() + "\\print.bmp";
cv::imwrite(filename, dst_mat);
#endif
*/
/*
#ifdef _DEBUG
std::string filename = GetCurrentDir() + "\\print.bmp";
cv::imwrite(filename, dst_mat);
#endif
*/
return dst_mat;
}

View File

@@ -5,15 +5,20 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MeoAsstGui"
mc:Ignorable="d"
Title="MeoAssistance-明日方舟辅助" Height="500" Width="400">
Title="Meo明日方舟辅助" Height="500" Width="400" Loaded="OnLoaded">
<Grid>
<CheckBox x:Name="checkBox_useMedicine" Content="吃理智药" HorizontalAlignment="Left" Margin="50,100,0,0" VerticalAlignment="Top" Checked="checkBox_useMedicine_Checked" Unchecked="checkBox_useMedicine_Checked" IsChecked="True"/>
<CheckBox x:Name="checkBox_useStone" Content="吃石头" HorizontalAlignment="Left" Margin="50,150,0,0" VerticalAlignment="Top" Checked="checkBox_useStone_Checked" Unchecked="checkBox_useStone_Checked"/>
<TextBox x:Name="textBox_useStone" HorizontalAlignment="Left" Height="23" Margin="112,148,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_useStone_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
<Label x:Name="label_stoneNumber" Content="颗" HorizontalAlignment="Left" Margin="164,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-5.771,-6.291"/>
<Button x:Name="button_startSanity" Content="开始刷理智" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,280,0,0" VerticalAlignment="Top" Width="300" Height="50" Click="button_Click_stop"/>
<Button x:Name="button_startSanity" Content="开始刷理智" HorizontalAlignment="Left" Margin="50,270,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,350,0,0" VerticalAlignment="Top" Width="300" Height="50" Click="button_Click_stop"/>
<Label x:Name="catch_status" Content="" HorizontalAlignment="Left" Margin="50,30,0,0" VerticalAlignment="Top"/>
<Button x:Name="button_visit" Content="访问基建" HorizontalAlignment="Left" Margin="230,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
<Button x:Name="button_visit" Content="访问基建" HorizontalAlignment="Left" Margin="230,270,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
<Label x:Name="exec_times" Content="" HorizontalAlignment="Left" Margin="230,30,0,0" VerticalAlignment="Top"/>
<Label x:Name="stone_times" Content="" HorizontalAlignment="Left" Margin="230,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.702,0.403"/>
<CheckBox x:Name="checkBox_maxTimes" Content="指定次数" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Checked="checkBox_maxTimes_Checked" Unchecked="checkBox_maxTimes_Checked"/>
<TextBox x:Name="textBox_maxTimes" HorizontalAlignment="Left" Height="23" Margin="124,198,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_maxTimes_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
<Label x:Name="label" Content="次" HorizontalAlignment="Left" Margin="176,193,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.397,-0.745"/>
</Grid>
</Window>

View File

@@ -13,6 +13,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Threading;
namespace MeoAsstGui
{
@@ -22,38 +23,56 @@ namespace MeoAsstGui
public partial class MainWindow : Window
{
[DllImport("MeoAssistance.dll")] static public extern IntPtr CreateAsst();
[DllImport("MeoAssistance.dll")] static public extern void DestoryAsst(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern bool AsstCatchSimulator(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern void AsstStart(IntPtr ptr, string task);
[DllImport("MeoAssistance.dll")] static public extern void AsstStop(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
[DllImport("MeoAssistance.dll")] static private extern IntPtr CreateAsst();
[DllImport("MeoAssistance.dll")] static private extern void DestoryAsst(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static private extern bool AsstCatchSimulator(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static private extern void AsstStart(IntPtr ptr, string task);
[DllImport("MeoAssistance.dll")] static private extern void AsstStop(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static private extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
[DllImport("MeoAssistance.dll")]
static private extern bool AsstGetParam(
IntPtr p_asst, string type, string param,
[In, Out] StringBuilder lp_string, int buffer_size);
private IntPtr p_asst;
UpdateDialog updateDialog;
private DispatcherTimer update_times = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
p_asst = CreateAsst();
}
~MainWindow()
{
DestoryAsst(p_asst);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
updateDialog = new UpdateDialog();
updateDialog.CheckUpdateAndShowDialog();
updateDialog.Close();
p_asst = CreateAsst();
update_times.Tick += new EventHandler(updateExecTimes);
update_times.Interval = TimeSpan.FromSeconds(1);
}
private void button_Click_startSanity(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchSimulator(p_asst);
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "SanityBegin");
update_times.Start();
}
private void button_Click_stop(object sender, RoutedEventArgs e)
{
AsstStop(p_asst);
catch_status.Content = "";
update_times.Stop();
exec_times.Content = "";
stone_times.Content = "";
}
private void checkBox_useMedicine_Checked(object sender, RoutedEventArgs e)
@@ -91,5 +110,39 @@ namespace MeoAsstGui
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "VisitBegin");
}
private void updateExecTimes(object sender, EventArgs e)
{
StringBuilder buff_start = new StringBuilder(16);
AsstGetParam(p_asst, "task.execTimes", "StartButton2", buff_start, 16);
exec_times.Content = "已开始行动 " + buff_start + " 次";
if (checkBox_useStone.IsChecked == true)
{
StringBuilder buff_stone = new StringBuilder(16);
AsstGetParam(p_asst, "task.execTimes", "StoneConfirm", buff_stone, 16);
stone_times.Content = "已碎石 " + buff_stone + " 个";
}
}
private void checkBox_maxTimes_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_maxTimes.IsChecked == true)
{
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", textBox_maxTimes.Text);
}
else
{
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", int.MaxValue.ToString());
}
}
private void textBox_maxTimes_TextChanged(object sender, TextChangedEventArgs e)
{
if (checkBox_maxTimes.IsChecked == true)
{
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", textBox_maxTimes.Text);
}
}
}
}

View File

@@ -26,7 +26,7 @@
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<ApplicationVersion>0.1.0.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@@ -54,6 +54,9 @@
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -75,6 +78,9 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="UpdateDialog.xaml.cs">
<DependentUpon>UpdateDialog.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -87,6 +93,10 @@
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="UpdateDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
@@ -126,6 +136,9 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Resource Include="favicon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource</PostBuildEvent>

View File

@@ -0,0 +1,16 @@
<Window x:Class="MeoAsstGui.UpdateDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MeoAsstGui"
mc:Ignorable="d"
Title="有新版本" Height="500" Width="400">
<Grid>
<Label x:Name="label_tag" Content="" HorizontalAlignment="Center" Margin="50,25,53.333,0" VerticalAlignment="Top" Height="50" Width="290" FontSize="24"/>
<Label x:Name="label_body" Content="" HorizontalAlignment="Left" Margin="50,80,0,0" VerticalAlignment="Top" Height="281" Width="290" FontSize="16"/>
<Button x:Name="button_confirm" Content="前往下载" HorizontalAlignment="Left" Margin="50,366,0,0" VerticalAlignment="Top" Width="120" Height="60" Click="button_confirm_Click"/>
<Button x:Name="button_cancer" Content="下次一定" HorizontalAlignment="Left" Margin="220,366,0,0" VerticalAlignment="Top" Width="120" Height="60" Click="button_cancer_Click"/>
</Grid>
</Window>

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
namespace MeoAsstGui
{
/// <summary>
/// UpdateDialog.xaml 的交互逻辑
/// </summary>
public partial class UpdateDialog : Window
{
[DllImport("MeoAssistance.dll")]
static private extern bool CheckVersionUpdate(
[In, Out] StringBuilder tag, int tag_bufsize,
[In, Out] StringBuilder html_url, int html_bufsize,
[In, Out] StringBuilder body, int body_bufsize);
public UpdateDialog()
{
InitializeComponent();
}
private String m_htmlUrl;
public void CheckUpdateAndShowDialog()
{
StringBuilder tag = new StringBuilder(64);
StringBuilder html_url = new StringBuilder(512);
StringBuilder body = new StringBuilder(4096);
bool ret = CheckVersionUpdate(tag, 64, html_url, 512, body, 4096);
if (!ret)
{
return;
}
label_tag.Content = "新版本:" + tag;
byte[] buffer1 = Encoding.Default.GetBytes(body.ToString());
byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);
string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);
strBuffer = strBuffer.Replace("\\r\\n", "\r\n");
label_body.Content = strBuffer.Substring(0, 128) + "\n......";
m_htmlUrl = html_url.ToString();
ShowDialog();
}
private void button_cancer_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void button_confirm_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start(m_htmlUrl);
Close();
}
}
}

BIN
MeoAsstGui/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -44,9 +44,14 @@ A game assistance for Arknights
兼容但需要手动设置分辨率设置中心——引擎设置——分辨率设置——1280x720——保存后重启模拟器
#### MuMu手游助手 && MuMu模拟器
#### MuMu模拟器
不兼容,MuMu所有的窗口句柄均不响应SendMessage鼠标消息但官方提供了adb的方式进行控制有时间再做
MuMu是个奇葩,它的所有的窗口句柄均不响应SendMessage鼠标消息
- MuMu模拟器
非常勉强的使用adb控制的方式兼容了刷理智的功能需要在模拟器设置里把分辨率设置成1280x720。建议使用"Sanity.exe"而不是图形化界面因为adb控制台窗口会一直往出弹
- MuMu手游助手星云引擎
不兼容,可见未来内也想不到什么好主意来兼容的
## 使用说明
@@ -86,8 +91,9 @@ A game assistance for Arknights
- [x] 代理失败的情况
- [x] 支持等级提升
- [x] 支持自动勾选代理指挥
- [ ] 支持刷指定次数
- [x] 支持刷指定次数
- [x] 自动吃石头(根据设置,指定数量)
- [ ] 指定刷XX个某材料
- [ ] 支持凌晨4点更新数据
- [ ] 结束界面自动截图,可用于上传企鹅物流
- [ ] 持续监视理智,一有就自动刷掉
@@ -100,9 +106,13 @@ A game assistance for Arknights
- [x] 更换算法为模板匹配找图,而不是当前的区域相似度对比
- [x] 优化算法效率,添加缓存功能
- [x] 优化任务队列,减少不必要的计算
- [ ] 掉落材料计数
- [ ] 窗口分辨率自适应
- [ ] 进一步优化任务队列效率
- [x] 其他
- [x] 尝试减小程序体积
- [x] 检查程序更新
- [ ] 程序自动更新
## 致谢

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -1,9 +1,17 @@
#include "Assistance.h"
#include "Updater.h"
int main(int argc, char** argv)
{
using namespace asst;
bool up = Updater::instance().has_new_version();
if (up) {
auto && info = Updater::instance().get_version_info();
std::cout << "ÓÐа汾£º" << info.tag_name << std::endl;
std::cout << "µØÖ·£º" << info.html_url << std::endl;
}
Assistance asst;
auto ret = asst.setSimulator();

Submodule meojson updated: e66deff929...d6d07f5e6c

BIN
resource/CollectCredit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
resource/CreditStore.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
resource/Mall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
resource/PopupCancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
resource/PopupConfirm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -147,6 +147,64 @@
"height": 769,
"xOffset": 0,
"yOffset": -42
},
"MuMuAsst": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - 星云引擎"
}
],
"adbControl": {
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
"connect": " connect 127.0.0.1:7555",
"click": " shell input tap [x] [y]"
},
"width": 1280,
"height": 809,
"xOffset": 0,
"yOffset": -36
},
"MuMuEmulator": {
"window": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "明日方舟 - MuMu模拟器"
}
],
"adbControl": {
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
"connect": " connect 127.0.0.1:7555",
"click": " shell input tap [x] [y]"
},
"width": 1280,
"height": 809,
"xOffset": 0,
"yOffset": -36
}
},
"tasks": {
@@ -167,7 +225,7 @@
},
"UsePrts": {
"filename": "UsePrts.png",
"threshold": 0.97,
"threshold": 0.8,
"type": "clickSelf",
"next": [
"StartButton1"
@@ -175,7 +233,7 @@
},
"StartButton1": {
"filename": "StartButton1.png",
"threshold": 0.94,
"threshold": 0.8,
"type": "clickSelf",
"next": [
"StartButton2",
@@ -184,18 +242,15 @@
]
},
"StartButton2": {
"id": 2,
"filename": "StartButton2.png",
"threshold": 0.99,
"type": "clickSelf",
"rearDelay": 10000,
"rearDelay": 20000,
"next": [
"PRTS"
]
},
"PRTS": {
"filename": "PRTS.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"PRTS",
@@ -221,7 +276,6 @@
},
"Loading": {
"filename": "Loading.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"StartButton1"
@@ -229,7 +283,6 @@
},
"UseMedicine": {
"filename": "UseMedicine.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"MedicineConfirm"
@@ -237,7 +290,6 @@
},
"MedicineConfirm": {
"filename": "MedicineConfirm.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"StartButton1"
@@ -245,7 +297,6 @@
},
"UseStone": {
"filename": "UseStone.png",
"threshold": 0.99,
"type": "doNothing",
"next": [
"StoneConfirm"
@@ -253,7 +304,6 @@
},
"StoneConfirm": {
"filename": "MedicineConfirm.png",
"threshold": 0.98,
"type": "clickSelf",
"maxTimes": 0,
"next": [
@@ -262,7 +312,6 @@
},
"PrtsErrorConfirm": {
"filename": "PrtsErrorConfirm.png",
"threshold": 0.98,
"type": "doNothing",
"next": [
"AbandonAction"
@@ -270,7 +319,6 @@
},
"AbandonAction": {
"filename": "AbandonAction.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"Random"
@@ -286,21 +334,19 @@
"StartToVisit",
"VisitNext",
"VisitNextBlack",
"Return"
"ReturnToFriends"
]
},
"Return": {
"ReturnToFriends": {
"filename": "Return.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"Friends",
"Return"
"ReturnToFriends"
]
},
"Friends": {
"filename": "Friends.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"FriendsList"
@@ -308,7 +354,6 @@
},
"FriendsList": {
"filename": "FriendsList.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"StartToVisit"
@@ -316,7 +361,6 @@
},
"StartToVisit": {
"filename": "StartToVisit.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"VisitNext"
@@ -324,23 +368,74 @@
},
"VisitNext": {
"filename": "VisitNext.png",
"threshold": 0.999,
"type": "clickSelf",
"maxTimes": 10,
"threshold": 0.999,
"maxTimes": 21,
"exceededNext": [
"ReturnToMall"
],
"next": [
"VisitNext",
"VisitNextBlack"
]
},
"ReturnToMall": {
"filename": "Return.png",
"type": "clickSelf",
"next": [
"Mall",
"ReturnToMall",
"ReturnToMallConfirm"
]
},
"ReturnToMallConfirm": {
"filename": "PopupConfirm.png",
"type": "clickSelf",
"next": [
"ReturnToMall"
]
},
"Mall": {
"filename": "Mall.png",
"type": "clickSelf",
"next": [
"CreditStore"
]
},
"CreditStore": {
"filename": "CreditStore.png",
"threshold": 0.89,
"rearDelay": 1000,
"type": "clickSelf",
"next": [
"CollectCredit",
"Stop"
]
},
"CollectCredit": {
"filename": "CollectCredit.png",
"type": "clickSelf",
"next": [
"Stop"
]
},
"VisitLimited": {
"filename": "VisitLimited.png",
"threshold": 0.65,
"type": "stop",
"next": []
"type": "doNothing",
"next": [
"ReturnToMall"
]
},
"VisitNextBlack": {
"filename": "VisitNextBlack.png",
"threshold": 0.98,
"type": "doNothing",
"next": [
"ReturnToMall"
]
},
"Stop": {
"filename": "",
"threshold": 0,
"type": "stop",
"next": []
}

2
update_resource.bat Normal file
View File

@@ -0,0 +1,2 @@
xcopy /e /y /i resource x64\Debug\resource
xcopy /e /y /i resource x64\Release\resource