新增战斗中的游泳检测 (#2315)

This commit is contained in:
kaedelcb
2025-10-10 02:51:38 +08:00
committed by GitHub
parent a10cdc32d0
commit 8dcf563b31
8 changed files with 153 additions and 32 deletions

View File

@@ -6,6 +6,10 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using BetterGenshinImpact.GameTask;
using BetterGenshinImpact.GameTask.AutoPathing.Model;
using BetterGenshinImpact.GameTask.Common;
using Microsoft.Extensions.Logging;
namespace BetterGenshinImpact.Core.Config;

View File

@@ -131,6 +131,8 @@ public partial class AutoFightConfig : ObservableObject
[ObservableProperty]
private string _kazuhaPartyName = "";
[ObservableProperty]
private bool _swimmingEnabled = false;
/// <summary>
/// 战斗超时,单位秒

View File

@@ -50,6 +50,7 @@ public class AutoFightParam : BaseTaskParam<AutoFightTask>
GuardianCombatSkip = autoFightConfig.GuardianCombatSkip;
SkipModel = autoFightConfig.SkipModel;
GuardianAvatarHold = autoFightConfig.GuardianAvatarHold;
SwimmingEnabled = autoFightConfig.SwimmingEnabled;
}
public FightFinishDetectConfig FinishDetectConfig { get; set; } = new();
@@ -70,6 +71,7 @@ public class AutoFightParam : BaseTaskParam<AutoFightTask>
public bool GuardianCombatSkip { get; set; } = false;
public bool SkipModel = false;
public bool GuardianAvatarHold = false;
public static bool SwimmingEnabled { get; set; } = false;
public AutoFightParam(string? strategyName = null) : base(null, null)
{
@@ -124,5 +126,6 @@ public class AutoFightParam : BaseTaskParam<AutoFightTask>
GuardianCombatSkip = autoFightConfig.GuardianCombatSkip;
SkipModel = autoFightConfig.SkipModel;
GuardianAvatarHold = autoFightConfig.GuardianAvatarHold;
SwimmingEnabled = autoFightConfig.SwimmingEnabled;
}
}

View File

@@ -20,6 +20,7 @@ using OpenCvSharp;
using BetterGenshinImpact.Helpers;
using Vanara;
using Microsoft.Extensions.DependencyInjection;
using BetterGenshinImpact.GameTask.AutoPathing.Model;
namespace BetterGenshinImpact.GameTask.AutoFight;
@@ -43,6 +44,9 @@ public class AutoFightTask : ISoloTask
public static bool FightStatusFlag { get; set; } = false;
// 战斗点位
public static WaypointForTrack? FightWaypoint {get; set;} = null;
private class TaskFightFinishDetectConfig
{
public int DelayTime = 1500;

View File

@@ -20,6 +20,10 @@ using static BetterGenshinImpact.GameTask.Common.TaskControl;
using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.GameTask.AutoFight.Assets;
using BetterGenshinImpact.ViewModel.Pages;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Model;
using BetterGenshinImpact.GameTask.AutoPathing;
using BetterGenshinImpact.GameTask.AutoPathing.Model;
using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum;
namespace BetterGenshinImpact.GameTask.AutoFight.Model;
@@ -113,6 +117,67 @@ public class Avatar
Sleep(600, ct);
TpForRecover(ct, new RetryException("检测到复苏界面,存在角色被击败,前往七天神像复活"));
}
else if(AutoFightParam.SwimmingEnabled && AutoFightTask.FightStatusFlag && SwimmingConfirm(region))
{
if (AutoFightTask.FightWaypoint is not null)
{
if (!SwimmingConfirm(CaptureToRectArea())) //二次确认
{
return;
}
Logger.LogInformation("游泳检测:尝试回到战斗地点");
var pathExecutor = new PathExecutor(ct);
try
{
pathExecutor.FaceTo(AutoFightTask.FightWaypoint).Wait(2000, ct);
AutoFightTask.FightWaypoint.MoveMode = MoveModeEnum.Fly.Code;//改为跳飞
Simulation.SendInput.Mouse.RightButtonDown();
pathExecutor.MoveTo(AutoFightTask.FightWaypoint).Wait(15000, ct);
AutoFightTask.FightWaypoint = null;//执行后清空,即每次战斗只执行一次,第二次直接去七天神像
Simulation.SendInput.Mouse.RightButtonUp();
}
catch (Exception ex)
{
Logger.LogWarning(ex, "游泳检测:回到战斗地点异常");
}
Simulation.ReleaseAllKey();
if (!SwimmingConfirm(CaptureToRectArea()))
{
Logger.LogInformation("游泳检测:游泳脱困成功");
return;
}
Logger.LogWarning("游泳检测:回到战斗地点失败");
}
Logger.LogWarning("战斗过程检测到游泳,前往七天神像重试");
TpForRecover(ct, new RetryException("战斗过程检测到游泳,前往七天神像重试"));
}
}
/// <summary>
/// 游泳检测(色块连通性检测)
/// 游泳时右下角会出现鼠标图标,带有黄色色块,不受改按键影响
/// </summary>
private static bool SwimmingConfirm(Region region)
{
var mask = OpenCvCommonHelper.Threshold(region.ToImageRegion().DeriveCrop(1819, 1025, 9, 11).SrcMat,
new Scalar(242, 223, 39),new Scalar(255, 233, 44));
var labels = new Mat();
var stats = new Mat();
var centroids = new Mat();
var numLabels = Cv2.ConnectedComponentsWithStats(mask, labels, stats, centroids,
connectivity: PixelConnectivity.Connectivity4, ltype: MatType.CV_32S);
labels.Dispose();
stats.Dispose();
centroids.Dispose();
return numLabels > 1;
}
/// <summary>

View File

@@ -37,6 +37,7 @@ using BetterGenshinImpact.GameTask.AutoPathing;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Common.Exceptions;
using BetterGenshinImpact.GameTask.Common.Map.Maps;
using BetterGenshinImpact.GameTask.AutoFight;
namespace BetterGenshinImpact.GameTask.AutoPathing;
@@ -213,6 +214,9 @@ public class PathExecutor
if ((!string.IsNullOrEmpty(waypoint.Action) && !_skipOtherOperations) ||
waypoint.Action == ActionEnum.CombatScript.Code)
{
//战斗前的节点记录,用于游泳检测回到战斗节点
AutoFightTask.FightWaypoint = waypoint.Action == ActionEnum.Fight.Code ? waypoint : null;
// 执行 action
await AfterMoveToTarget(waypoint);
}

View File

@@ -971,32 +971,51 @@
Margin="0,0,36,0"
IsChecked="{Binding Config.AutoFightConfig.KazuhaPickupEnabled, Mode=TwoWay}" />
</Grid>
<Grid Margin="16">
<Grid Margin="16,10,16,16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ui:TextBlock Grid.Row="0"
Grid.Column="0"
FontTypography="Body"
Text="战斗超时(秒)"
Text="自动战斗超时(秒)"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="0"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="当战斗超过一定时间后,自动停止战斗"
Text="到达指定时间后,自动停止战斗"
TextWrapping="Wrap" />
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
HorizontalContentAlignment="Center"
Margin="0,0,36,0"
MinWidth="120"
Text="{Binding Config.AutoFightConfig.Timeout}" />
Margin="10,0,20,0"
MinWidth="50"
Text="{Binding Config.AutoFightConfig.Timeout}"/>
<ui:TextBlock Grid.Row="0"
Grid.Column="2"
FontTypography="Body"
Text="游泳检测(自动战斗过程中)"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="2"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="先回战斗节点,失败则去七天神像"
TextWrapping="Wrap" />
<ui:ToggleSwitch Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="3"
Margin="10,0,36,0"
HorizontalAlignment="Right"
IsChecked="{Binding Config.AutoFightConfig.SwimmingEnabled, Mode=TwoWay}" />
</Grid>
</StackPanel>
</ui:CardExpander>

View File

@@ -1447,32 +1447,52 @@
Margin="0,0,36,0"
Text="{Binding PathingConfig.AutoFightConfig.KazuhaPartyName}" />
</Grid>
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ui:TextBlock Grid.Row="0"
Grid.Column="0"
FontTypography="Body"
Text="战斗超时(秒)"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="0"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="当战斗超过一定时间后,自动停止战斗"
TextWrapping="Wrap" />
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
MinWidth="120"
Margin="0,0,36,0"
Text="{Binding PathingConfig.AutoFightConfig.Timeout}" />
</Grid>
<Grid Margin="16,10,16,16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ui:TextBlock Grid.Row="0"
Grid.Column="0"
FontTypography="Body"
Text="自动战斗超时(秒)"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="0"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="到达指定时间后,自动停止战斗"
TextWrapping="Wrap" />
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
HorizontalContentAlignment="Center"
Margin="10,0,20,0"
MinWidth="50"
Text="{Binding PathingConfig.AutoFightConfig.Timeout}"/>
<ui:TextBlock Grid.Row="0"
Grid.Column="2"
FontTypography="Body"
Text="游泳检测(自动战斗过程中)"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="2"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="先回战斗节点,失败则去七天神像"
TextWrapping="Wrap" />
<ui:ToggleSwitch Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="3"
Margin="10,0,36,0"
HorizontalAlignment="Right"
IsChecked="{Binding PathingConfig.AutoFightConfig.SwimmingEnabled, Mode=TwoWay}" />
</Grid>
</StackPanel>
</ui:CardExpander>
<!-- 自动吃食物 -->