using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using BetterGenshinImpact.Core.Recognition.ONNX; using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.GameTask.Model.Area; using BetterGenshinImpact.View.Drawable; using Microsoft.Extensions.Logging; using OpenCvSharp; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; namespace BetterGenshinImpact.GameTask.Common.Job; /// /// 扫描拾取任务 /// 请在安全地区使用 /// public class ScanPickTask { private readonly BgiYoloV8Predictor _predictor = BgiYoloV8PredictorFactory.GetPredictor(@"Assets\Model\World\bgi_world.onnx"); private readonly double _dpi = TaskContext.Instance().DpiScale; private readonly RECT _realCaptureRect = TaskContext.Instance().SystemInfo.CaptureAreaRect; public async Task Start(CancellationToken ct) { try { await DoOnce(ct); } catch (Exception e) { Logger.LogDebug(e, "拾取周边物品异常"); Logger.LogError("拾取周边物品异常: {Msg}", e.Message); } finally { VisionContext.Instance().DrawContent.ClearAll(); } } public async Task DoOnce(CancellationToken ct) { await ResetCamera(ct); for (int n = 0; n < 5; n++) // 最多跑5次 { var hasDrops = false; // 旋转视角 for (var i = 0; i < 20; i++) { var ra = CaptureToRectArea(); var resultDic = _predictor.Detect(ra); // 过滤出可拾取物品 var pickItems = resultDic.Where(x => x.Key is "drops" or "ore") .SelectMany(x => x.Value).ToList(); if (pickItems.Count > 0) { hasDrops = true; // 把鼠标位置和物品位置重合 MoveCursorTo(pickItems.First(), ra); await Delay(100, ct); // 物体越小,距离越远 await WalkForward(ct); break; } Simulation.SendInput.Mouse.MoveMouseBy((int)(300 * _dpi), 0); await Delay(100, ct); } if (!hasDrops) { break; } } } private static async Task WalkForward(CancellationToken ct) { Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W); await Delay(1000, ct); Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); } private void MoveCursorTo(Rect item, ImageRegion ra) { var centerX = (item.Left + item.Right) / 2; var centerY = (item.Top + item.Bottom) / 2; var dx = centerX - ra.Width / 2; var dy = centerY - ra.Height / 2; var r = _realCaptureRect.Width * 1.0 / ra.Width; // 缩放比例 Simulation.SendInput.Mouse.MoveMouseBy((int)(dx * r * _dpi), (int)(dy * r * _dpi)); } // 回正 并下移视角 private async Task ResetCamera(CancellationToken ct) { // Simulation.SendInput.Keyboard.Mouse.MiddleButtonClick(); // await Delay(500, ct); Simulation.SendInput.Keyboard.Mouse.MoveMouseBy(0, (int)(500 * _dpi)); await Delay(100, ct); } }