using BetterGenshinImpact.Core.Recognition.OCR; using BetterGenshinImpact.GameTask.AutoSkip.Model; using BetterGenshinImpact.GameTask.Common; using BetterGenshinImpact.View.Drawable; using Microsoft.Extensions.Logging; using OpenCvSharp; using Sdcb.PaddleOCR; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace BetterGenshinImpact.GameTask.AutoSkip; /// /// 重新探索派遣 /// /// 必须在已经有探索派遣完成的情况下使用 /// /// 于 4.3 版本废弃 /// [Obsolete] public class ExpeditionTask { private static readonly List ExpeditionCharacterList = []; private int _expeditionCount = 0; public void Run(CaptureContent content) { InitConfig(); var assetScale = TaskContext.Instance().SystemInfo.AssetScale; ReExplorationGameArea(content); for (var i = 0; i <= 4; i++) { if (_expeditionCount >= 5) { // 最多派遣5人 break; } else { content.CaptureRectArea .Derive(new Rect((int)(110 * assetScale), (int)((145 + 70 * i) * assetScale), (int)(60 * assetScale), (int)(33 * assetScale))) .Click(); TaskControl.Sleep(500); ReExplorationGameArea(content); } } TaskControl.Logger.LogInformation("探索派遣:{Text}", "重新派遣完成"); VisionContext.Instance().DrawContent.ClearAll(); } private void InitConfig() { var str = TaskContext.Instance().Config.AutoSkipConfig.AutoReExploreCharacter; if (!string.IsNullOrEmpty(str)) { ExpeditionCharacterList.Clear(); str = str.Replace(",", ","); str.Split(',').ToList().ForEach(x => ExpeditionCharacterList.Add(x.Trim())); TaskContext.Instance().Config.AutoSkipConfig.AutoReExploreCharacter = string.Join(",", ExpeditionCharacterList); } } private void ReExplorationGameArea(CaptureContent content) { var captureRect = TaskContext.Instance().SystemInfo.CaptureAreaRect; var assetScale = TaskContext.Instance().SystemInfo.AssetScale; for (var i = 0; i < 5; i++) { var result = CaptureAndOcr(content, new Rect(0, 0, captureRect.Width - (int)(480 * assetScale), captureRect.Height)); var rect = result.FindRectByText("探险完成"); // TODO i>1 的时候,可以通过关键词“探索派遣限制 4 / 5 ”判断是否已经派遣完成? if (rect != Rect.Empty) { // 点击探险完成下方的人物头像 content.CaptureRectArea.Derive(new Rect(rect.X, rect.Y + (int)(50 * assetScale), rect.Width, (int)(80 * assetScale))).Click(); TaskControl.Sleep(100); // 重新截图 找领取 result = CaptureAndOcr(content); rect = result.FindRectByText("领取"); if (rect != Rect.Empty) { using var ra = content.CaptureRectArea.Derive(rect); ra.Click(); //TaskControl.Logger.LogInformation("探索派遣:点击{Text}", "领取"); TaskControl.Sleep(200); // 点击空白区域继续 ra.Click(); TaskControl.Sleep(250); // 选择角色 result = CaptureAndOcr(content); rect = result.FindRectByText("选择角色"); if (rect != Rect.Empty) { content.CaptureRectArea.Derive(rect).Click(); TaskControl.Sleep(400); // 等待动画 var success = SelectCharacter(content); if (success) { _expeditionCount++; } } } else { TaskControl.Logger.LogWarning("探索派遣:找不到 {Text} 文字", "领取"); } } else { break; } } } private bool SelectCharacter(CaptureContent content) { var captureRect = TaskContext.Instance().SystemInfo.CaptureAreaRect; var result = CaptureAndOcr(content, new Rect(0, 0, captureRect.Width / 2, captureRect.Height)); if (result.RegionHasText("角色选择")) { var cards = GetCharacterCards(result); if (cards.Count > 0) { var card = cards.FirstOrDefault(c => c.Idle && c.Name != null && ExpeditionCharacterList.Contains(c.Name)) ?? cards.First(c => c.Idle); var rect = card.Rects.First(); using var ra = content.CaptureRectArea.Derive(rect); ra.Click(); TaskControl.Logger.LogInformation("探索派遣:派遣 {Name}", card.Name); TaskControl.Sleep(500); return true; } } return false; } /// /// 根据文字识别结果 获取所有角色选项 /// /// /// private List GetCharacterCards(PaddleOcrResult result) { var captureRect = TaskContext.Instance().SystemInfo.CaptureAreaRect; var assetScale = TaskContext.Instance().SystemInfo.AssetScale; var ocrResultRects = result.Regions .Select(x => x.ToOcrResultRect()) .Where(r => r.Rect.X + r.Rect.Width < captureRect.Width / 2) .OrderBy(r => r.Rect.Y) .ThenBy(r => r.Rect.X) .ToList(); var cards = new List(); foreach (var ocrResultRect in ocrResultRects) { if (ocrResultRect.Text.Contains("时间缩短") || ocrResultRect.Text.Contains("奖励增加") || ocrResultRect.Text.Contains("暂无加成")) { var card = new ExpeditionCharacterCard(); card.Rects.Add(ocrResultRect.Rect); card.Addition = ocrResultRect.Text; foreach (var ocrResultRect2 in ocrResultRects) { if (ocrResultRect2.Rect.Y > ocrResultRect.Rect.Y - 50 * assetScale && ocrResultRect2.Rect.Y + ocrResultRect2.Rect.Height < ocrResultRect.Rect.Y + ocrResultRect.Rect.Height) { if (ocrResultRect2.Text.Contains("探险完成") || ocrResultRect2.Text.Contains("探险中")) { card.Idle = false; var name = ocrResultRect2.Text.Replace("探险完成", "").Replace("探险中", "").Replace("/", "").Trim(); if (!string.IsNullOrEmpty(name)) { card.Name = name; } } else if (!ocrResultRect2.Text.Contains("时间缩短") && !ocrResultRect2.Text.Contains("奖励增加") && !ocrResultRect2.Text.Contains("暂无加成")) { card.Name = ocrResultRect2.Text; } card.Rects.Add(ocrResultRect2.Rect); } } if (!string.IsNullOrEmpty(card.Name)) { cards.Add(card); } else { TaskControl.Logger.LogWarning("探索派遣:存在未找到角色命的识别内容"); } } } return cards; } private readonly Pen _pen = new(Color.Red, 1); private PaddleOcrResult CaptureAndOcr(CaptureContent content) { using var ra = TaskControl.CaptureToRectArea(); var result = OcrFactory.Paddle.OcrResult(ra.SrcGreyMat); //VisionContext.Instance().DrawContent.PutOrRemoveRectList("OcrResultRects", result.ToRectDrawableList(_pen)); return result; } private PaddleOcrResult CaptureAndOcr(CaptureContent content, Rect rect) { using var ra = TaskControl.CaptureToRectArea(); var result = OcrFactory.Paddle.OcrResult(ra.SrcGreyMat); //VisionContext.Instance().DrawContent.PutOrRemoveRectList("OcrResultRects", result.ToRectDrawableList(_pen)); return result; } }