using RichCreator.Utility;
|
using RichCreator.Utility.Captures;
|
using RichCreator.Utility.CV;
|
using RichCreator.Utility.InputControl;
|
using RichCreator.Utility.Structs;
|
using RichCreator.Utility.Utilitys;
|
using Emgu.CV;
|
using Emgu.CV.Structure;
|
using RichCreator.Models;
|
using RichCreator.ViewModels;
|
using System;
|
using System.IO;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using System.Windows;
|
using System.Windows.Controls;
|
using ZTImage.Configuration;
|
using ZTImage.Log;
|
using RichCreator.Utility.Maps;
|
using RichCreator.Dnf;
|
using System.Windows.Interop;
|
using RichCreator.Maps.Kalete;
|
using ZTImage.Collections;
|
using System.Collections.Generic;
|
|
namespace RichCreator
|
{
|
/// <summary>
|
/// MainWindow.xaml 的交互逻辑
|
/// </summary>
|
public partial class MainWindow : Window
|
{
|
private ConfigViewModel viewModel;
|
public MainWindow()
|
{
|
InitializeComponent();
|
G.Instance.EnableWriter(this.writeDebug, this.writeInfo, this.writeRemainTime, this.CancelConfirm,this.stopTaskUI);
|
viewModel = new ConfigViewModel();
|
this.DataContext = viewModel;
|
}
|
|
|
private JobMonitor monitor;
|
private bool isRunning = false;
|
|
#region events
|
/// <summary>
|
/// 开始运行
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void Run_Click(object sender, RoutedEventArgs e)
|
{
|
MapType mapType = (MapType)this.taskName.SelectedIndex;
|
if (mapType == MapType.TestSpeed)
|
{
|
//测速
|
G.Instance.InfoWriter("开始测速");
|
TestSpeed();
|
return;
|
}
|
else if (mapType == MapType.TestSkill)
|
{
|
//测技能
|
G.Instance.InfoWriter("开始测技能");
|
TestSkill();
|
return;
|
}
|
else if (mapType == MapType.ReadRolePosition)
|
{
|
//读取角色位置
|
G.Instance.InfoWriter("开始测角色位置");
|
ReadRolePosition();
|
return;
|
}
|
else if (mapType == MapType.TestToNextDoor)
|
{
|
//测试进入下一关的门
|
G.Instance.InfoWriter("开始测进门");
|
TestToNextDoor();
|
return;
|
}
|
|
if (isRunning)
|
{
|
monitor.Stop();
|
stopTaskUI();
|
return;
|
}
|
|
G.Instance.DebugWriter("开始运行,2秒后开始控制,请不要移动鼠标!~");
|
RunningButton.IsEnabled = false;
|
Task.Run(() => {
|
Thread.Sleep(2000);
|
if (!TestHardware())
|
{
|
if (!TestHardware())
|
{
|
G.Instance.DebugWriter("检测硬件未通过");
|
stopTaskUI();
|
return;
|
}
|
}
|
G.Instance.DebugWriter("硬件检测通过");
|
|
this.monitor = new JobMonitor(mapType);
|
monitor.Start();
|
|
startTaskUI();
|
});
|
|
|
}
|
|
|
/// <summary>
|
/// 清空日志
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void ClearLog_Click(object sender, RoutedEventArgs e)
|
{
|
this.LogTB.Text = string.Empty;
|
}
|
|
/// <summary>
|
/// 点击检测按钮
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void BtnTestDo_Click(object sender, RoutedEventArgs e)
|
{
|
if (this.RemainTimeTB.Text.Trim() == "032j")
|
{
|
testTempVar = true;
|
|
}
|
else
|
{
|
testTempVar = false;
|
}
|
manualre.Set();
|
}
|
|
/// <summary>
|
/// 取消重试
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void CancelTry_Click(object sender, RoutedEventArgs e)
|
{
|
cancelReTry = true;
|
}
|
|
/// <summary>
|
/// GPD路径浏览
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void BrowserGPDPath_Click(object sender, RoutedEventArgs e)
|
{
|
string exePath = string.Empty;
|
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
|
ofd.DefaultExt = ".exe";
|
ofd.Filter = "tgp_daemon|*.exe";
|
ofd.Multiselect = false;
|
if (ofd.ShowDialog() == true)
|
{
|
exePath = ofd.FileName;
|
}
|
else
|
{
|
return;
|
}
|
|
if (File.Exists(exePath))
|
{
|
this.viewModel.TGPDaemonPath = exePath;
|
return;
|
}
|
}
|
|
/// <summary>
|
/// 保存配置
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void ConfigSave_Click(object sender, RoutedEventArgs e)
|
{
|
this.viewModel.SaveConfig();
|
MessageBox.Show("配置更新成功");
|
}
|
#endregion
|
|
|
/// <summary>
|
/// 测速
|
/// </summary>
|
private void TestSpeed()
|
{
|
ZTRectangle gameRect = ZTRectangle.Empty;
|
WindowUtils.GetDnfRect(out gameRect);
|
Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(gameRect.End.X - gameRect.Start.X + 1, gameRect.End.Y - gameRect.Start.Y + 1);
|
Task.Run(() =>
|
{
|
WindowUtils.SetDnfToTop();
|
Thread.Sleep(1000);
|
Image<Rgb, byte> image = ScreenCapture.Instance.CaptureScreenReturnImage();
|
CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
|
ZTPoint start = DnfCVHelper.FindRole(hsvImage, gameRect);
|
|
|
G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, HIDCode.LeftArrow);
|
Thread.Sleep(30);
|
G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
|
Thread.Sleep(30);
|
G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, HIDCode.LeftArrow);
|
Thread.Sleep(800);
|
G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
|
|
//G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, HIDCode.DownArrow);
|
//Thread.Sleep(1000);
|
//G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
|
|
|
|
//G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, HIDCode.LeftArrow);
|
//Thread.Sleep(1000);
|
//G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
|
|
|
image = ScreenCapture.Instance.CaptureScreenReturnImage();
|
CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
|
ZTPoint end = DnfCVHelper.FindRole(hsvImage, gameRect);
|
|
|
G.Instance.InfoWriter($"from:{start},to:{end},distanceX:{end.X - start.X},distanceY:{end.Y - start.Y}");
|
});
|
}
|
|
/// <summary>
|
/// 测技能
|
/// </summary>
|
private void TestSkill()
|
{
|
ZTRectangle gameRect = ZTRectangle.Empty;
|
WindowUtils.GetDnfRect(out gameRect);
|
Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(gameRect.End.X - gameRect.Start.X + 1, gameRect.End.Y - gameRect.Start.Y + 1);
|
Task.Run(() => {
|
WindowUtils.SetDnfToTop();
|
Thread.Sleep(10);
|
|
KaleteMap map = new KaleteMap(gameRect, CancellationToken.None);
|
Int32 lastHouseIndex = -1;
|
Int32 houseIndex = -1;
|
|
while (true)
|
{
|
Image<Rgb, byte> image = ScreenCapture.Instance.CaptureScreenReturnImage();
|
if (map.MiniMap.GetCurrentHouseIndex(out houseIndex, image))
|
{
|
if (houseIndex != lastHouseIndex)
|
{
|
G.Instance.InfoWriter($"entry house:{houseIndex}");
|
lastHouseIndex = houseIndex;
|
//发技能
|
map.EntryHousePrework(houseIndex, lastHouseIndex);
|
}
|
}
|
Thread.Sleep(500);
|
}
|
});
|
}
|
|
/// <summary>
|
/// 读取角色位置
|
/// </summary>
|
private void ReadRolePosition()
|
{
|
ZTRectangle gameRect = ZTRectangle.Empty;
|
WindowUtils.GetDnfRect(out gameRect);
|
Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(gameRect.End.X - gameRect.Start.X + 1, gameRect.End.Y - gameRect.Start.Y + 1);
|
Task.Run(() => {
|
WindowUtils.SetDnfToTop();
|
Thread.Sleep(1000);
|
Image<Rgb, byte> image = ScreenCapture.Instance.CaptureScreenReturnImage();
|
CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
|
ZTPoint rolePosition = DnfCVHelper.FindRole(hsvImage, gameRect);
|
|
|
G.Instance.InfoWriter($"角色位置读取成功,CBPosition:{rolePosition},Half Position:{DnfRole.CBToHalfPosition(rolePosition)},Foot Position:{DnfRole.CBToFootPosition(rolePosition)}");
|
});
|
}
|
|
/// <summary>
|
/// 测试进入下一关的门
|
/// </summary>
|
private void TestToNextDoor()
|
{
|
ZTRectangle gameRect = ZTRectangle.Empty;
|
WindowUtils.GetDnfRect(out gameRect);
|
|
HouseInfo house = new HouseInfo(1, MapType.Kalete, false, null,null);
|
DnfRole role = new DnfRole(gameRect);
|
role.SetHouse(house);
|
|
|
Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(gameRect.End.X - gameRect.Start.X, gameRect.End.Y - gameRect.Start.Y );
|
Task.Run(() => {
|
WindowUtils.SetDnfToTop();
|
Thread.Sleep(10);
|
|
Image<Rgb, byte> image = ScreenCapture.Instance.CaptureScreenReturnImage();
|
image.ROI = new System.Drawing.Rectangle(gameRect.Start.X, gameRect.Start.Y, gameRect.End.X - gameRect.Start.X, gameRect.End.Y - gameRect.Start.Y);
|
CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
|
image.ROI = System.Drawing.Rectangle.Empty;
|
|
//定位点
|
ParametersPoint locationCoor = DnfCVHelper.GetLocationPoint(image, gameRect);
|
if (locationCoor.Equals(ParametersPoint.Empty))
|
{
|
//找不到定位点
|
G.Instance.InfoWriter("找不到定位点");
|
return;
|
}
|
|
|
ZTPoint rolePosition = DnfCVHelper.FindRole(hsvImage, gameRect);
|
role.UpdatePosition(rolePosition);
|
|
ZTPoint start=house.ScreenToMapCoordinate(DnfRole.CBToHalfPosition(rolePosition), locationCoor);
|
|
|
ZTPoint roleFootPosition = house.ScreenToMapCoordinate(role.Position, locationCoor);
|
ZTPoint ngp = DnfRole.HalfToFootPosition(house.HousePathInfo.NextGates[0].Point);
|
role.MoveToMapPoint(roleFootPosition, ngp);
|
|
G.Instance.InfoWriter($"测试进入下一关的门完成");
|
});
|
}
|
|
|
#region 测试硬件
|
//测试硬件的中间变量
|
private bool testTempVar = false;
|
private AutoResetEvent manualre = new AutoResetEvent(false);
|
|
/// <summary>
|
/// 测试硬件是否正常工作
|
/// </summary>
|
/// <returns></returns>
|
private bool TestHardware()
|
{
|
testTempVar = false;
|
Utility.Structs.ZTPoint btnPosition = Utility.Structs.ZTPoint.Empty;
|
Utility.Structs.ZTPoint txtPosition = Utility.Structs.ZTPoint.Empty;
|
using (ManualResetEvent mre = new ManualResetEvent(false))
|
{
|
//等待读取位置成功
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
this.RemainTimeTB.Text = string.Empty;
|
btnPosition = GetElementClickPosition(this.btnTestDo);
|
txtPosition = GetElementClickPosition(this.RemainTimeTB);
|
mre.Set();
|
}));
|
if (!mre.WaitOne(1000))
|
{
|
return false;
|
}
|
}
|
|
|
//输入文字
|
G.Instance.InputControl.MoveToAndClick(txtPosition);
|
G.Instance.InputControl.InputString("032j");
|
|
//点检测
|
G.Instance.InputControl.MoveToAndClick(btnPosition);
|
|
bool rtt = manualre.WaitOne(8000);
|
if (!rtt)
|
{
|
return false;
|
}
|
if (testTempVar)
|
{
|
return true;
|
}
|
|
return false;
|
}
|
|
|
|
/// <summary>
|
/// 获取控件位置
|
/// </summary>
|
/// <param name="element"></param>
|
/// <returns></returns>
|
private ZTPoint GetElementClickPosition(Control element)
|
{
|
Point t = element.PointToScreen(new Point(0, 0));
|
Utility.Structs.ZTPoint t1 = new Utility.Structs.ZTPoint((Int32)(t.X + element.ActualWidth / 2), (Int32)(t.Y + element.ActualHeight / 2));
|
return t1;
|
}
|
#endregion
|
|
|
#region 显示
|
/// <summary>
|
/// 输出调试信息
|
/// </summary>
|
/// <param name="msg"></param>
|
private void writeDebug(string msg)
|
{
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
string content = DateTime.Now.ToString("dd日HH:mm:ss") + "->" + msg;
|
this.debugMessage.Text = content;
|
}));
|
|
Trace.Debug(msg);
|
}
|
|
/// <summary>
|
/// 输出关键信息
|
/// </summary>
|
/// <param name="msg"></param>
|
private void writeInfo(string msg)
|
{
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
if (string.IsNullOrEmpty(msg))
|
{
|
this.LogTB.Text = string.Empty;
|
return;
|
}
|
string content = DateTime.Now.ToString("dd日HH:mm:ss") + "->" + msg + "\r\n";
|
this.LogTB.AppendText(content);
|
this.LogTB.ScrollToEnd();
|
}));
|
|
Trace.Info(msg);
|
}
|
|
bool cancelReTry = false;
|
/// <summary>
|
/// 弹出提示,并带有倒计时
|
/// </summary>
|
/// <param name="msg"></param>
|
/// <param name="remainMillSecond"></param>
|
private bool CancelConfirm(Int64 remainMillSecond)
|
{
|
bool retry = true;
|
ManualResetEvent mre = new ManualResetEvent(false);
|
|
//启用取消按钮
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
cancelReTry = false;
|
btnCancelTry.IsEnabled = true;
|
mre.Set();
|
}));
|
mre.WaitOne();
|
mre.Reset();
|
|
//计时,并判断是否取消
|
for (int remainSecond = (Int32)remainMillSecond / 1000; remainSecond >= 0; remainSecond--)
|
{
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
btnCancelTry.Content = "取消重试(" + remainSecond + ")";
|
mre.Set();
|
}));
|
mre.WaitOne();
|
mre.Reset();
|
if (cancelReTry)
|
{
|
//取消重试
|
retry = false;
|
break;
|
}
|
Thread.Sleep(1000);
|
}
|
|
//禁用取消按钮
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
cancelReTry = false;
|
btnCancelTry.IsEnabled = false;
|
btnCancelTry.Content = "取消重试";
|
mre.Set();
|
}));
|
mre.WaitOne();
|
mre.Reset();
|
mre.Close();
|
return retry;
|
}
|
|
|
/// <summary>
|
/// 输出剩余时间
|
/// </summary>
|
/// <param name="remaintime"></param>
|
private void writeRemainTime(Int64 remaintime)
|
{
|
//更新倒计时
|
string rt = "--:--";
|
if (remaintime >= 0)
|
{
|
Int64 min = remaintime / 60;
|
Int64 sec = remaintime % 60;
|
rt = min.ToString().PadLeft(2, '0') + ":" + sec.ToString().PadLeft(2, '0');
|
}
|
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
{
|
this.RemainTimeTB.Text = rt;
|
}));
|
}
|
|
/// <summary>
|
/// 开始任务UI设置
|
/// </summary>
|
private void startTaskUI()
|
{
|
//文字设成停止运行
|
this.Dispatcher.BeginInvoke((Action)(() => {
|
RunningButton.Content = "停止";
|
RunningButton.IsEnabled = true;
|
isRunning = true;
|
}));
|
}
|
|
/// <summary>
|
/// 停止任务
|
/// </summary>
|
private void stopTaskUI()
|
{
|
//文字设成停止运行
|
this.Dispatcher.BeginInvoke((Action)(() => {
|
RunningButton.Content = "开始";
|
RunningButton.IsEnabled = true;
|
isRunning = false;
|
}));
|
}
|
|
#endregion
|
|
|
|
private int hotKeyID = 2839;
|
/// <summary>
|
/// 热键消息
|
/// </summary>
|
const int WindowsMessageHotkey = 786;
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
{
|
//注册热键
|
IntPtr intPtr = (new WindowInteropHelper(this)).Handle;
|
if (!SystemHotKey.RegHotKey(intPtr, hotKeyID, SystemHotKey.KeyModifiers.None, System.Windows.Forms.Keys.Home))
|
{
|
MessageBox.Show("热键不可用,其它应用已经占用热键");
|
}
|
else
|
{
|
ComponentDispatcher.ThreadPreprocessMessage += (ref MSG Message, ref bool Handled) =>
|
{
|
// 判断是否热键消息
|
if (Message.message == WindowsMessageHotkey)
|
{
|
// 获取热键id
|
var id = Message.wParam.ToInt32();
|
// 执行热键回调方法(执行时需要判断是否与注册的热键匹配)
|
if (id == hotKeyID)
|
{
|
Run_Click(this, new RoutedEventArgs());
|
}
|
|
}
|
};
|
|
}
|
|
}
|
|
|
|
private void Window_Unloaded(object sender, RoutedEventArgs e)
|
{
|
//注销热键
|
IntPtr intPtr = (new WindowInteropHelper(this)).Handle;
|
SystemHotKey.UnRegHotKey(intPtr, hotKeyID);
|
}
|
}
|
}
|