From e408750d09cf769d72e0dd33b8fd87f4ca952e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Fri, 5 Apr 2024 19:54:37 +0800 Subject: [PATCH] auto track mission --- BetterGenshinImpact.Test/MainWindow.xaml.cs | 2 +- .../Simple/AllMap/MatchTemplateTest.cs | 10 + .../BetterGenshinImpact.csproj | 6 + .../GameTask/AutoSkip/AutoSkipTrigger.cs | 5 - .../GameTask/AutoSkip/AutoTrackTask.cs | 296 ++++++++++++++++++ .../GameTask/AutoSkip/Model/AutoTrackParam.cs | 11 + ...point_28x.png => blue_track_point_28x.png} | Bin ...int_28x.png => yellow_track_point_28x.png} | Bin .../Common/Element/Assets/ElementAssets.cs | 15 +- .../GameTask/Common/TaskControl.cs | 11 + .../GameTask/Model/BaseIndependentTask.cs | 11 + .../GameTask/Model/IndependentTaskEnum.cs | 4 +- .../GameTask/Model/RectArea.cs | 26 +- .../GameTask/TaskTriggerDispatcher.cs | 6 + BetterGenshinImpact/Helpers/ClickOffset.cs | 7 +- BetterGenshinImpact/Helpers/StringUtils.cs | 22 +- .../View/Pages/TaskSettingsPage.xaml | 106 +++++-- .../Pages/TaskSettingsPageViewModel.cs | 53 ++++ 18 files changed, 547 insertions(+), 44 deletions(-) create mode 100644 BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs create mode 100644 BetterGenshinImpact/GameTask/AutoSkip/Model/AutoTrackParam.cs rename BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/{blue_task_point_28x.png => blue_track_point_28x.png} (100%) rename BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/{yellow_task_point_28x.png => yellow_track_point_28x.png} (100%) create mode 100644 BetterGenshinImpact/GameTask/Model/BaseIndependentTask.cs diff --git a/BetterGenshinImpact.Test/MainWindow.xaml.cs b/BetterGenshinImpact.Test/MainWindow.xaml.cs index a1ef7986..73121911 100644 --- a/BetterGenshinImpact.Test/MainWindow.xaml.cs +++ b/BetterGenshinImpact.Test/MainWindow.xaml.cs @@ -37,7 +37,7 @@ public partial class MainWindow : Window private void DoMatchTemplateTest(object sender, System.Windows.RoutedEventArgs e) { - MatchTemplateTest.TestMenu(); + MatchTemplateTest.TestTrack(); } private void DoMatchTest(object sender, System.Windows.RoutedEventArgs e) diff --git a/BetterGenshinImpact.Test/Simple/AllMap/MatchTemplateTest.cs b/BetterGenshinImpact.Test/Simple/AllMap/MatchTemplateTest.cs index ae04cabc..0ca04dec 100644 --- a/BetterGenshinImpact.Test/Simple/AllMap/MatchTemplateTest.cs +++ b/BetterGenshinImpact.Test/Simple/AllMap/MatchTemplateTest.cs @@ -25,6 +25,16 @@ public class MatchTemplateTest Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\x1.png", src2); } + public static void TestTrack() + { + var tar = new Mat(@"E:\HuiTask\更好的原神\自动剧情\任务剧情与地图追踪\blue_task_point_28x.png", ImreadModes.Grayscale); + var src = new Mat(@"E:\HuiTask\更好的原神\自动剧情\任务剧情与地图追踪\202404050232291883.png", ImreadModes.Grayscale); + var src2 = src.Clone(); + var p = MatchTemplateHelper.MatchTemplate(src, tar, TemplateMatchModes.CCoeffNormed, null, 0.1); + Cv2.Rectangle(src2, new Rect(p.X, p.Y, tar.Width, tar.Height), new Scalar(0, 0, 255), 1); + Cv2.ImWrite(@"E:\HuiTask\更好的原神\自动剧情\任务剧情与地图追踪\rec_b1.png", src2); + } + public static void TestMenu() { var tar = new Mat(@"D:\HuiPrograming\Projects\CSharp\MiHoYo\BetterGenshinImpact\BetterGenshinImpact\GameTask\Common\Element\Assets\1920x1080\paimon_menu.png", ImreadModes.Color); diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index 1cf7e93e..e5fab82d 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -364,6 +364,9 @@ Always + + Always + Always @@ -448,6 +451,9 @@ Always + + Always + Always diff --git a/BetterGenshinImpact/GameTask/AutoSkip/AutoSkipTrigger.cs b/BetterGenshinImpact/GameTask/AutoSkip/AutoSkipTrigger.cs index e2a8fc79..2ec61924 100644 --- a/BetterGenshinImpact/GameTask/AutoSkip/AutoSkipTrigger.cs +++ b/BetterGenshinImpact/GameTask/AutoSkip/AutoSkipTrigger.cs @@ -232,11 +232,6 @@ public class AutoSkipTrigger : ITaskTrigger return false; } - private bool AutoTrack(CaptureContent content) - { - return false; - } - private void HangoutOptionChoose(CaptureContent content) { var selectedRects = MatchTemplateHelper.MatchOnePicForOnePic(content.CaptureRectArea.SrcGreyMat, _autoSkipAssets.HangoutSelectedMat); diff --git a/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs b/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs new file mode 100644 index 00000000..0dba29a1 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs @@ -0,0 +1,296 @@ +using BetterGenshinImpact.Core.Recognition; +using BetterGenshinImpact.Core.Recognition.OCR; +using BetterGenshinImpact.Core.Recognition.OpenCv; +using BetterGenshinImpact.Core.Simulator; +using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; +using BetterGenshinImpact.GameTask.AutoSkip.Model; +using BetterGenshinImpact.GameTask.Common.Element.Assets; +using BetterGenshinImpact.GameTask.Model; +using BetterGenshinImpact.GameTask.QuickTeleport.Assets; +using BetterGenshinImpact.Helpers; +using BetterGenshinImpact.Service.Notification; +using BetterGenshinImpact.View.Drawable; +using Microsoft.Extensions.Logging; +using OpenCvSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using BetterGenshinImpact.GameTask.Common; +using BetterGenshinImpact.GameTask.Common.BgiVision; +using BetterGenshinImpact.ViewModel.Pages; +using Vanara.PInvoke; +using static BetterGenshinImpact.GameTask.Common.TaskControl; +using WinRT; + +namespace BetterGenshinImpact.GameTask.AutoSkip; + +public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask +{ + // /// + // /// 准备好前进了 + // /// + // private bool _readyMoveForward = false; + + /// + /// 任务距离 + /// + private Rect _missionDistanceRect = Rect.Empty; + + public async void Start() + { + var hasLock = false; + try + { + hasLock = await TaskSemaphore.WaitAsync(0); + if (!hasLock) + { + Logger.LogError("启动自动追踪功能失败:当前存在正在运行中的独立任务,请不要重复执行任务!"); + return; + } + + SystemControl.ActivateWindow(); + + TrackMission(); + } + catch (NormalEndException e) + { + Logger.LogInformation("自动追踪中断:" + e.Message); + // NotificationHelper.SendTaskNotificationWithScreenshotUsing(b => b.Domain().Cancelled().Build()); + } + catch (Exception e) + { + Logger.LogError(e.Message); + Logger.LogDebug(e.StackTrace); + // NotificationHelper.SendTaskNotificationWithScreenshotUsing(b => b.Domain().Failure().Build()); + } + finally + { + VisionContext.Instance().DrawContent.ClearAll(); + TaskSettingsPageViewModel.SetSwitchAutoTrackButtonText(false); + Logger.LogInformation("→ {Text}", "自动追踪结束"); + + if (hasLock) + { + TaskSemaphore.Release(); + } + } + } + + private void TrackMission() + { + // 确认在主界面才会执行跟随任务 + var ra = GetRectAreaFromDispatcher(); + var paimonMenuRa = ra.Find(ElementAssets.Instance.PaimonMenuRo); + if (!paimonMenuRa.IsExist()) + { + Sleep(5000, param.Cts); + return; + } + + // 任务文字有动效,等待2s重新截图 + Simulation.SendInputEx.Mouse.MoveMouseBy(0, 7000); + Sleep(2000, param.Cts); + + // OCR 任务文字 在小地图下方 + var textRaList = OcrMissionTextRaList(paimonMenuRa); + if (textRaList.Count == 0) + { + Logger.LogInformation("未找到任务文字"); + Sleep(5000, param.Cts); + return; + } + + // 从任务文字中提取距离 + var distance = GetDistanceFromMissionText(textRaList); + Logger.LogInformation("任务追踪:{Text}", "距离" + distance + "m"); + if (distance >= 150) + { + // 距离大于150米,先传送到最近的传送点 + // J 打开任务 切换追踪打开地图 中心点就是任务点 + Simulation.SendInputEx.Keyboard.KeyPress(User32.VK.VK_J); + Sleep(800, param.Cts); + // TODO 识别是否在任务界面 + // 切换追踪 + var btn = ra.DerivePoint(CaptureRect.Width - 250, CaptureRect.Height - 60); + btn.ClickCenter(); + Sleep(200, param.Cts); + btn.ClickCenter(); + Sleep(1500, param.Cts); + + // 寻找所有传送点 + ra = GetRectAreaFromDispatcher(); + var tpPointList = MatchTemplateHelper.MatchMultiPicForOnePic(ra.SrcGreyMat, QuickTeleportAssets.Instance.MapChooseIconGreyMatList); + if (tpPointList.Count > 0) + { + // 选中离中心点最近的传送点 + var centerX = ra.Width / 2; + var centerY = ra.Height / 2; + var minDistance = double.MaxValue; + var nearestRect = Rect.Empty; + foreach (var tpPoint in tpPointList) + { + var distanceTp = Math.Sqrt(Math.Pow(Math.Abs(tpPoint.X - centerX), 2) + Math.Pow(Math.Abs(tpPoint.Y - centerY), 2)); + if (distanceTp < minDistance) + { + minDistance = distanceTp; + nearestRect = tpPoint; + } + } + + ra.Derive(nearestRect).ClickCenter(); + // 等待自动传送完成 + Sleep(2000, param.Cts); + + if (Bv.IsInBigMapUi(GetRectAreaFromDispatcher())) + { + Logger.LogWarning("仍旧在大地图界面,传送失败"); + } + else + { + Sleep(500, param.Cts); + NewRetry.Do(() => + { + if (!Bv.IsInMainUi(GetRectAreaFromDispatcher())) + { + Logger.LogInformation("未进入到主界面,继续等待"); + throw new RetryException("未进入到主界面"); + } + }, TimeSpan.FromSeconds(1), 100); + StartTrackPoint(); + } + } + else + { + Logger.LogWarning("未找到传送点"); + } + } + else + { + StartTrackPoint(); + } + } + + private void StartTrackPoint() + { + // V键直接追踪 + Simulation.SendInputEx.Keyboard.KeyPress(User32.VK.VK_V); + Sleep(3000, param.Cts); + + var ra = GetRectAreaFromDispatcher(); + var blueTrackPointRa = ra.Find(ElementAssets.Instance.BlueTrackPoint); + if (blueTrackPointRa.IsExist()) + { + MakeBlueTrackPointDirectlyAbove(); + } + else + { + Logger.LogWarning("首次未找到追踪点"); + } + } + + /// + /// 找到追踪点并调整方向 + /// + private void MakeBlueTrackPointDirectlyAbove() + { + // return new Task(() => + // { + int prevMoveX = 0; + bool wDown = false; + while (!param.Cts.Token.IsCancellationRequested) + { + var ra = GetRectAreaFromDispatcher(); + var blueTrackPointRa = ra.Find(ElementAssets.Instance.BlueTrackPoint); + if (blueTrackPointRa.IsExist()) + { + // 调整整体高度 + var centerY = blueTrackPointRa.Y + blueTrackPointRa.Height / 2; + if (centerY > CaptureRect.Height / 2) + { + Simulation.SendInputEx.Mouse.MoveMouseBy(-100, 0); + if (wDown) + { + Simulation.SendInputEx.Keyboard.KeyUp(User32.VK.VK_W); + wDown = false; + } + + continue; + } + + // 调整方向 + var centerX = blueTrackPointRa.X + blueTrackPointRa.Width / 2; + var moveX = centerX - CaptureRect.Width / 2; + if (moveX != 0) + { + Simulation.SendInputEx.Mouse.MoveMouseBy(moveX, 0); + } + + if (moveX == 0 || prevMoveX * moveX < 0) + { + if (!wDown) + { + Simulation.SendInputEx.Keyboard.KeyDown(User32.VK.VK_W); + wDown = true; + } + } + + if (Math.Abs(moveX) < 50 && Math.Abs(centerY - CaptureRect.Height / 2) < 200) + { + if (wDown) + { + Simulation.SendInputEx.Keyboard.KeyUp(User32.VK.VK_W); + wDown = false; + } + // 识别距离 + var text = OcrFactory.Paddle.OcrWithoutDetector(ra.SrcGreyMat[_missionDistanceRect]); + if (StringUtils.TryExtractPositiveInt(text) is > -1 and <= 3) + { + Logger.LogInformation("任务追踪:到达目标,识别结果[{Text}]", text); + break; + } + Logger.LogInformation("任务追踪:到达目标"); + break; + } + + prevMoveX = moveX; + } + else + { + // 随机移动 + Logger.LogInformation("未找到追踪点"); + } + + Simulation.SendInputEx.Mouse.MoveMouseBy(0, 500); // 保证俯视角 + Sleep(100); + } + // }); + } + + private int GetDistanceFromMissionText(List textRaList) + { + // 打印所有任务文字 + var text = textRaList.Aggregate(string.Empty, (current, textRa) => current + textRa.Text.Trim() + "|"); + Logger.LogInformation("任务追踪:{Text}", text); + + foreach (var textRa in textRaList) + { + if (textRa.Text.Length < 8 && (textRa.Text.Contains("m") || textRa.Text.Contains("M"))) + { + _missionDistanceRect = textRa.ConvertRelativePositionToCaptureArea(); + return StringUtils.TryExtractPositiveInt(textRa.Text); + } + } + + return -1; + } + + private List OcrMissionTextRaList(RectArea paimonMenuRa) + { + return GetRectAreaFromDispatcher().FindMulti(new RecognitionObject + { + RecognitionType = RecognitionTypes.Ocr, + RegionOfInterest = new Rect(paimonMenuRa.X, paimonMenuRa.Y - 15 + 210, + (int)(300 * AssetScale), (int)(100 * AssetScale)) + }); + } +} diff --git a/BetterGenshinImpact/GameTask/AutoSkip/Model/AutoTrackParam.cs b/BetterGenshinImpact/GameTask/AutoSkip/Model/AutoTrackParam.cs new file mode 100644 index 00000000..36bdeca4 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoSkip/Model/AutoTrackParam.cs @@ -0,0 +1,11 @@ +using System.Threading; +using BetterGenshinImpact.GameTask.Model; + +namespace BetterGenshinImpact.GameTask.AutoSkip.Model; + +public class AutoTrackParam : BaseTaskParam +{ + public AutoTrackParam(CancellationTokenSource cts) : base(cts) + { + } +} diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/blue_task_point_28x.png b/BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/blue_track_point_28x.png similarity index 100% rename from BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/blue_task_point_28x.png rename to BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/blue_track_point_28x.png diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/yellow_task_point_28x.png b/BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/yellow_track_point_28x.png similarity index 100% rename from BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/yellow_task_point_28x.png rename to BetterGenshinImpact/GameTask/Common/Element/Assets/1920x1080/yellow_track_point_28x.png diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/ElementAssets.cs b/BetterGenshinImpact/GameTask/Common/Element/Assets/ElementAssets.cs index 1ff3fabf..ce2868ff 100644 --- a/BetterGenshinImpact/GameTask/Common/Element/Assets/ElementAssets.cs +++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/ElementAssets.cs @@ -10,11 +10,10 @@ public class ElementAssets : BaseAssets public RecognitionObject BtnWhiteCancel; public RecognitionObject BtnBlackConfirm; public RecognitionObject PaimonMenuRo; + public RecognitionObject BlueTrackPoint; private ElementAssets() { - var info = TaskContext.Instance().SystemInfo; - // 按钮 BtnWhiteConfirm = new RecognitionObject { @@ -44,8 +43,18 @@ public class ElementAssets : BaseAssets Name = "PaimonMenu", RecognitionType = RecognitionTypes.TemplateMatch, TemplateImageMat = GameTaskManager.LoadAssetImage(@"Common\Element", "paimon_menu.png"), - RegionOfInterest = new Rect(0, 0, info.CaptureAreaRect.Width / 4, info.CaptureAreaRect.Height / 4), + RegionOfInterest = new Rect(0, 0, CaptureRect.Width / 4, CaptureRect.Height / 4), DrawOnWindow = false }.InitTemplate(); + + // 任务追踪点位 + BlueTrackPoint = new RecognitionObject + { + Name = "BlueTrackPoint", + RecognitionType = RecognitionTypes.TemplateMatch, + TemplateImageMat = GameTaskManager.LoadAssetImage(@"Common\Element", "blue_track_point_28x.png"), + RegionOfInterest = new Rect((int)(300 * AssetScale), 0, CaptureRect.Width - (int)(600 * AssetScale), CaptureRect.Height), + DrawOnWindow = true + }.InitTemplate(); } } diff --git a/BetterGenshinImpact/GameTask/Common/TaskControl.cs b/BetterGenshinImpact/GameTask/Common/TaskControl.cs index f212efca..d2990a08 100644 --- a/BetterGenshinImpact/GameTask/Common/TaskControl.cs +++ b/BetterGenshinImpact/GameTask/Common/TaskControl.cs @@ -1,4 +1,5 @@ using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; +using BetterGenshinImpact.GameTask.Model; using Fischless.GameCapture; using Microsoft.Extensions.Logging; using System; @@ -132,8 +133,18 @@ public class TaskControl return CaptureToContent(TaskTriggerDispatcher.GlobalGameCapture); } + public static RectArea CaptureToRectArea() + { + return CaptureToContent().CaptureRectArea; + } + public static CaptureContent GetContentFromDispatcher() { return TaskTriggerDispatcher.Instance().GetLastCaptureContent(); } + + public static RectArea GetRectAreaFromDispatcher() + { + return GetContentFromDispatcher().CaptureRectArea; + } } diff --git a/BetterGenshinImpact/GameTask/Model/BaseIndependentTask.cs b/BetterGenshinImpact/GameTask/Model/BaseIndependentTask.cs new file mode 100644 index 00000000..65939d70 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Model/BaseIndependentTask.cs @@ -0,0 +1,11 @@ +using BetterGenshinImpact.Helpers; +using Vanara.PInvoke; + +namespace BetterGenshinImpact.GameTask.Model; + +public class BaseIndependentTask +{ + protected SystemInfo Info => TaskContext.Instance().SystemInfo; + protected RECT CaptureRect => TaskContext.Instance().SystemInfo.CaptureAreaRect; + protected double AssetScale => TaskContext.Instance().SystemInfo.AssetScale; +} diff --git a/BetterGenshinImpact/GameTask/Model/IndependentTaskEnum.cs b/BetterGenshinImpact/GameTask/Model/IndependentTaskEnum.cs index 5e809801..33b1ec79 100644 --- a/BetterGenshinImpact/GameTask/Model/IndependentTaskEnum.cs +++ b/BetterGenshinImpact/GameTask/Model/IndependentTaskEnum.cs @@ -2,9 +2,9 @@ public enum IndependentTaskEnum { - AutoGeniusInvokation, AutoWood, AutoFight, AutoDomain, -} \ No newline at end of file + AutoTrack, +} diff --git a/BetterGenshinImpact/GameTask/Model/RectArea.cs b/BetterGenshinImpact/GameTask/Model/RectArea.cs index 4f02a679..48def9c2 100644 --- a/BetterGenshinImpact/GameTask/Model/RectArea.cs +++ b/BetterGenshinImpact/GameTask/Model/RectArea.cs @@ -11,8 +11,10 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text.RegularExpressions; +using Microsoft.Extensions.Logging; using Sdcb.PaddleOCR; using Point = OpenCvSharp.Point; +using static BetterGenshinImpact.GameTask.Common.TaskControl; namespace BetterGenshinImpact.GameTask.Model; @@ -252,6 +254,11 @@ public class RectArea : IDisposable if (ro.RegionOfInterest != Rect.Empty) { // TODO roi 是可以加缓存的 + if (!(0 <= ro.RegionOfInterest.X && 0 <= ro.RegionOfInterest.Width && ro.RegionOfInterest.X + ro.RegionOfInterest.Width <= roi.Cols + && 0 <= ro.RegionOfInterest.Y && 0 <= ro.RegionOfInterest.Height && ro.RegionOfInterest.Y + ro.RegionOfInterest.Height <= roi.Rows)) + { + Logger.LogError("输入图像{W1}x{H1},模板ROI区域{H2}x{W2},边界溢出!", roi.Width, roi.Height, ro.RegionOfInterest.Width, ro.RegionOfInterest.Height); + } roi = new Mat(roi, ro.RegionOfInterest); } @@ -453,7 +460,12 @@ public class RectArea : IDisposable if (result.Regions.Length > 0) { - var resRaList = result.Regions.Select(r => this.Derive(r.Rect.BoundingRect() + new Point(ro.RegionOfInterest.X, ro.RegionOfInterest.Y))).ToList(); + var resRaList = result.Regions.Select(r => + { + var newRa = this.Derive(r.Rect.BoundingRect() + new Point(ro.RegionOfInterest.X, ro.RegionOfInterest.Y)); + newRa.Text = r.Text; + return newRa; + }).ToList(); if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) { VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name, result.ToRectDrawableListOffset(ro.RegionOfInterest.X, ro.RegionOfInterest.Y)); @@ -531,6 +543,18 @@ public class RectArea : IDisposable return new RectArea(rect, this); } + /// + /// 派生2x2区域(无图片) + /// 方便用于点击 + /// + /// + /// + /// + public RectArea DerivePoint(int x, int y) + { + return new RectArea(new Rect(x, y, 2, 2), this); + } + /// /// OCR识别 /// diff --git a/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs b/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs index 4a10e159..5071edda 100644 --- a/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs +++ b/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs @@ -21,6 +21,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using BetterGenshinImpact.GameTask.AutoSkip; +using BetterGenshinImpact.GameTask.AutoSkip.Model; using Vanara.PInvoke; namespace BetterGenshinImpact.GameTask @@ -216,6 +218,10 @@ namespace BetterGenshinImpact.GameTask { Task.Run(() => { new AutoDomainTask((AutoDomainParam)param).Start(); }); } + else if (taskType == IndependentTaskEnum.AutoTrack) + { + Task.Run(() => { new AutoTrackTask((AutoTrackParam)param).Start(); }); + } } public void Dispose() => Stop(); diff --git a/BetterGenshinImpact/Helpers/ClickOffset.cs b/BetterGenshinImpact/Helpers/ClickOffset.cs index 8ddcdafa..70b3d59e 100644 --- a/BetterGenshinImpact/Helpers/ClickOffset.cs +++ b/BetterGenshinImpact/Helpers/ClickOffset.cs @@ -1,10 +1,6 @@ using BetterGenshinImpact.GameTask; using BetterGenshinImpact.Helpers.Extensions; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace BetterGenshinImpact.Helpers; @@ -14,7 +10,6 @@ public class ClickOffset public int OffsetY { get; set; } public double AssetScale { get; set; } - public ClickOffset() { if (!TaskContext.Instance().IsInitialized) @@ -54,4 +49,4 @@ public class ClickOffset { ClickExtension.Move(OffsetX + (int)(x * AssetScale), OffsetY + (int)(y * AssetScale)); } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/Helpers/StringUtils.cs b/BetterGenshinImpact/Helpers/StringUtils.cs index 303dd92d..f2664d82 100644 --- a/BetterGenshinImpact/Helpers/StringUtils.cs +++ b/BetterGenshinImpact/Helpers/StringUtils.cs @@ -1,4 +1,6 @@ -namespace BetterGenshinImpact.Helpers; +using System.Text.RegularExpressions; + +namespace BetterGenshinImpact.Helpers; public class StringUtils { @@ -101,4 +103,22 @@ public class StringUtils return 0; } } + + public static int TryExtractPositiveInt(string text) + { + if (string.IsNullOrEmpty(text)) + { + return -1; + } + + try + { + text = Regex.Replace(text, @"[^0-9]+", ""); + return int.Parse(text); + } + catch + { + return -1; + } + } } diff --git a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml index d32ba0b3..8103d8cd 100644 --- a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml @@ -1,8 +1,8 @@  - 全自动打牌 - - + 全自动打牌 - 点击查看使用教程 @@ -201,9 +199,7 @@ Grid.Column="0" Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" TextWrapping="Wrap"> - 需要装备「王树瑞佑」 - - + 需要装备「王树瑞佑」 - 点击查看使用教程 @@ -293,9 +289,7 @@ Grid.Column="0" Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" TextWrapping="Wrap"> - 自动执行选择的战斗策略 - - + 自动执行选择的战斗策略 - 点击查看使用教程 @@ -394,9 +388,7 @@ Grid.Column="0" Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" TextWrapping="Wrap"> - 基于钟离的自动循环刷本 - - + 基于钟离的自动循环刷本 - 点击查看使用教程 @@ -515,12 +507,11 @@ Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" Text="如果电脑性能较差,寻找古树时间过久,可以尝试使用这个功能" TextWrapping="Wrap" /> - + @@ -541,12 +532,11 @@ Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" Text="如果电脑性能较差,开启秘境或者领取奖励的F点击不到,可以尝试此功能" TextWrapping="Wrap" /> - + @@ -603,6 +593,72 @@ + + + + + + + + + + + + + + 自动走路跟踪剧情任务,不支持每日任务 - + 点击查看使用教程 + + + + + + + + + + + + + + + + + + + + + +