using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.AutoFight.Assets;
using BetterGenshinImpact.GameTask.AutoFight.Model;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Model;
using BetterGenshinImpact.GameTask.AutoPathing.Handler;
using BetterGenshinImpact.GameTask.AutoPathing.Model;
using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum;
using BetterGenshinImpact.GameTask.AutoSkip;
using BetterGenshinImpact.GameTask.AutoSkip.Assets;
using BetterGenshinImpact.GameTask.AutoTrackPath;
using BetterGenshinImpact.GameTask.Common.BgiVision;
using BetterGenshinImpact.GameTask.Common.Job;
using BetterGenshinImpact.GameTask.Common.Map;
using BetterGenshinImpact.GameTask.Model.Area;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
using ActionEnum = BetterGenshinImpact.GameTask.AutoPathing.Model.Enum.ActionEnum;
namespace BetterGenshinImpact.GameTask.AutoPathing;
public class PathExecutor(CancellationToken ct)
{
private readonly CameraRotateTask _rotateTask = new(ct);
private readonly TrapEscaper _trapEscaper = new(ct);
private readonly BlessingOfTheWelkinMoonTask _blessingOfTheWelkinMoonTask = new();
private AutoSkipTrigger? _autoSkipTrigger;
private PathingPartyConfig? _partyConfig;
public PathingPartyConfig PartyConfig
{
get => _partyConfig ?? PathingPartyConfig.BuildDefault();
set => _partyConfig = value;
}
///
/// 判断是否中止路径追踪的条件
///
public Func? EndAction { get; set; }
private CombatScenes? _combatScenes;
// private readonly Dictionary _actionAvatarIndexMap = new();
private DateTime _elementalSkillLastUseTime = DateTime.MinValue;
private DateTime _useGadgetLastUseTime = DateTime.MinValue;
private const int RetryTimes = 2;
private int _inTrap = 0;
public async Task Pathing(PathingTask task)
{
if (!task.Positions.Any())
{
Logger.LogWarning("没有路径点,寻路结束");
return;
}
// 切换队伍
var pRaList = CaptureToRectArea().FindMulti(AutoFightAssets.Instance.PRa); // 判断是否联机
if (pRaList.Count > 0)
{
Logger.LogInformation("处于联机状态下,不切换队伍");
}
else
{
if (PartyConfig is { Enabled: false })
{
// 调度器未配置的情况下,根据路径追踪条件配置切换队伍
var partyName = FilterPartyNameByConditionConfig(task);
if (!await SwitchParty(partyName))
{
Logger.LogError("切换队伍失败,无法执行此路径!请检查路径追踪设置!");
return;
}
}
else if (!string.IsNullOrEmpty(PartyConfig.PartyName))
{
if (!await SwitchParty(PartyConfig.PartyName))
{
Logger.LogError("切换队伍失败,无法执行此路径!请检查配置组中的路径追踪配置!");
return;
}
}
}
// 校验路径是否可以执行
if (!await ValidateGameWithTask(task))
{
return;
}
InitializePathing(task);
// 转换、按传送点分割路径
var waypointsList = ConvertWaypointsForTrack(task.Positions);
await Delay(100, ct);
Navigation.WarmUp(); // 提前加载地图特征点
foreach (var waypoints in waypointsList)
{
for (var i = 0; i < RetryTimes; i++)
{
try
{
await ResolveAnomalies(); // 异常场景处理
foreach (var waypoint in waypoints)
{
await RecoverWhenLowHp(waypoint); // 低血量恢复
if (waypoint.Type == WaypointType.Teleport.Code)
{
await HandleTeleportWaypoint(waypoint);
}
else
{
await BeforeMoveToTarget(waypoint);
// Path不用走得很近,Target需要接近,但都需要先移动到对应位置
await MoveTo(waypoint);
if (waypoint.Type == WaypointType.Target.Code
// 除了 fight mining 之外的 action 都需要接近
|| (!string.IsNullOrEmpty(waypoint.Action)
&& waypoint.Action != ActionEnum.NahidaCollect.Code
&& waypoint.Action != ActionEnum.Fight.Code
&& waypoint.Action != ActionEnum.CombatScript.Code
&& waypoint.Action != ActionEnum.Mining.Code))
{
await MoveCloseTo(waypoint);
}
if (!string.IsNullOrEmpty(waypoint.Action))
{
// 执行 action
await AfterMoveToTarget(waypoint);
}
}
}
break;
}
catch (NormalEndException normalEndException)
{
Logger.LogInformation(normalEndException.Message);
break;
}
catch (RetryException retryException)
{
Logger.LogWarning(retryException.Message);
}
finally
{
// 不管咋样,松开所有按键
Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
Simulation.SendInput.Mouse.RightButtonUp();
}
}
}
}
private void InitializePathing(PathingTask task)
{
LogScreenResolution();
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage