Files
better-genshin-impact/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs
2024-12-28 21:29:42 +08:00

243 lines
7.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
using OpenCvSharp;
using System;
using System.Linq;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.AutoFight;
using Vanara.PInvoke;
using System.Threading;
using BetterGenshinImpact.GameTask.AutoSkip.Assets;
using BetterGenshinImpact.GameTask.GameLoading.Assets;
namespace BetterGenshinImpact.GameTask.Common.BgiVision;
/// <summary>
/// 模仿OpenCv的静态类
/// 用于原神的各类识别与控制操作
///
/// 此处主要是对游戏内的一些状态进行识别
/// </summary>
public static partial class Bv
{
public static string WhichGameUi()
{
throw new NotImplementedException();
}
/// <summary>
/// 是否在主界面
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool IsInMainUi(ImageRegion captureRa)
{
return captureRa.Find(ElementAssets.Instance.PaimonMenuRo).IsExist();
}
/// <summary>
/// 等待主界面加载完成
/// </summary>
/// <param name="ct"></param>
/// <param name="retryTimes"></param>
/// <returns></returns>
public static async Task<bool> WaitForMainUi(CancellationToken ct, int retryTimes = 10)
{
for (var i = 0; i < retryTimes; i++)
{
await TaskControl.Delay(1000, ct);
using var ra3 = TaskControl.CaptureToRectArea();
if (IsInMainUi(ra3))
{
return true;
}
}
return false;
}
/// <summary>
/// 在任意可以关闭的UI界面识别关闭按钮
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool IsInAnyClosableUi(ImageRegion captureRa)
{
return captureRa.Find(QuickTeleportAssets.Instance.MapCloseButtonRo).IsExist();
}
/// <summary>
/// 是否在队伍选择界面
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool IsInPartyViewUi(ImageRegion captureRa)
{
return captureRa.Find(ElementAssets.Instance.PartyBtnChooseView).IsExist();
}
/// <summary>
/// 等待队伍选择界面加载完成
/// </summary>
/// <param name="ct"></param>
/// <param name="retryTimes"></param>
/// <returns></returns>
public static async Task<bool> WaitForPartyViewUi(CancellationToken ct, int retryTimes = 5)
{
return await NewRetry.WaitForAction(() => IsInPartyViewUi(TaskControl.CaptureToRectArea()), ct, retryTimes);
}
/// <summary>
/// 是否在大地图界面
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool IsInBigMapUi(ImageRegion captureRa)
{
return captureRa.Find(QuickTeleportAssets.Instance.MapScaleButtonRo).IsExist();
}
/// <summary>
/// 大地图界面是否在地底
/// 鼠标悬浮在地下图标或者处于切换动画的时候可能会误识别
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool BigMapIsUnderground(ImageRegion captureRa)
{
return captureRa.Find(QuickTeleportAssets.Instance.MapUndergroundSwitchButtonRo).IsExist();
}
public static double GetBigMapScale(ImageRegion region)
{
var scaleRa = region.Find(QuickTeleportAssets.Instance.MapScaleButtonRo);
if (scaleRa.IsEmpty())
{
throw new Exception("当前未处于大地图界面不能使用GetBigMapScale方法");
}
// 452 ~ 627 间隔 35 和截图有关的截图高24
var start = QuickTeleportAssets.MapScaleButton1080StartY;
var end = QuickTeleportAssets.MapScaleButton1080EndY;
var cur = (scaleRa.Y + scaleRa.Height / 2.0) * TaskContext.Instance().SystemInfo.ZoomOutMax1080PRatio; // 转换到1080p坐标系,主要是小于1080p的情况
return (end * 1.0 - cur) / (end - start);
}
public static MotionStatus GetMotionStatus(ImageRegion captureRa)
{
var spaceExist = captureRa.Find(ElementAssets.Instance.SpaceKey).IsExist();
var xExist = captureRa.Find(ElementAssets.Instance.XKey).IsExist();
if (spaceExist)
{
return xExist ? MotionStatus.Climb : MotionStatus.Fly;
}
else
{
return MotionStatus.Normal;
}
}
/// <summary>
/// 是否出现复苏提示
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static bool IsInRevivePrompt(ImageRegion region)
{
using var confirmRectArea = region.Find(AutoFightContext.Instance.FightAssets.ConfirmRa);
if (!confirmRectArea.IsEmpty())
{
var list = region.FindMulti(new RecognitionObject
{
RecognitionType = RecognitionTypes.Ocr,
RegionOfInterest = new Rect(0, 0, region.Width, region.Height / 2)
});
if (list.Any(r => r.Text.Contains("复苏")))
{
return true;
}
}
return false;
}
/// <summary>
/// 是否出现全队死亡和复苏提示
/// </summary>
/// <param name="region"></param>
/// <returns></returns>
public static bool ClickIfInReviveModal(ImageRegion region)
{
var list = region.FindMulti(new RecognitionObject
{
RecognitionType = RecognitionTypes.Ocr,
RegionOfInterest = new Rect(0, region.Height / 4 * 3, region.Width, region.Height / 4)
});
var r = list.FirstOrDefault(r => r.Text.Contains("复苏"));
if (r != null)
{
r.Click();
return true;
}
return false;
}
/// <summary>
/// 当前角色是否低血量
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool CurrentAvatarIsLowHp(ImageRegion captureRa)
{
var assetScale = TaskContext.Instance().SystemInfo.AssetScale;
// 获取 (808, 1010) 位置的像素颜色
var pixelColor = captureRa.SrcMat.At<Vec3b>((int)(1010 * assetScale), (int)(808 * assetScale));
// 判断颜色是否是 (255, 90, 90)
return pixelColor is { Item2: 255, Item1: 90, Item0: 90 };
}
/// <summary>
/// 在空月祝福界面
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool IsInBlessingOfTheWelkinMoon(ImageRegion captureRa)
{
return captureRa.Find(GameLoadingAssets.Instance.WelkinMoonRo).IsExist();
}
/// <summary>
/// 是否在对话界面
/// </summary>
/// <param name="captureRa"></param>
/// <returns></returns>
public static bool IsInTalkUi(ImageRegion captureRa)
{
return captureRa.Find(AutoSkipAssets.Instance.DisabledUiButtonRo).IsExist();
}
/// <summary>
/// 等到对话界面加载完成
/// </summary>
/// <param name="ct"></param>
/// <param name="retryTimes"></param>
/// <returns></returns>
public static async Task<bool> WaitAndSkipForTalkUi(CancellationToken ct, int retryTimes = 5)
{
return await NewRetry.WaitForAction(() => IsInTalkUi(TaskControl.CaptureToRectArea()), ct, retryTimes, 500);
}
}
public enum MotionStatus
{
Normal, // 正常
Fly, // 飞行
Climb, // 攀爬
}