diff --git a/BetterGenshinImpact.Test/BetterGenshinImpact.Test.csproj b/BetterGenshinImpact.Test/BetterGenshinImpact.Test.csproj
index 94f70e0d..66a35680 100644
--- a/BetterGenshinImpact.Test/BetterGenshinImpact.Test.csproj
+++ b/BetterGenshinImpact.Test/BetterGenshinImpact.Test.csproj
@@ -5,6 +5,7 @@
net8.0-windows10.0.22621.0
enable
enable
+ true
true
diff --git a/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj b/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj
index 8c1de519..9a858568 100644
--- a/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj
+++ b/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj
@@ -4,6 +4,7 @@
net8.0-windows10.0.22621.0
enable
enable
+ true
x64
diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index b3ddee7d..11dd367a 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -6,6 +6,7 @@
enable
true
true
+ true
12.0
true
Assets\Images\logo.ico
diff --git a/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs b/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs
index 00ab7d8e..f1ecd877 100644
--- a/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs
+++ b/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs
@@ -27,6 +27,8 @@ public class PathExecutor(CancellationTokenSource cts)
private CameraRotateTask _rotateTask = new(cts);
+ private bool SkipWaypoint = false;
+
public async Task Pathing(PathingTask task)
{
_dpi = TaskContext.Instance().DpiScale;
@@ -55,6 +57,12 @@ public class PathExecutor(CancellationTokenSource cts)
{
// Path不用走得很近,Target需要接近,但都需要先移动到对应位置
await MoveTo(waypoint);
+ // 跳过路径点后,当前路径点不处理
+ if (SkipWaypoint)
+ {
+ SkipWaypoint = false;
+ continue;
+ }
if (waypoint.Type == WaypointType.Target.Code || !string.IsNullOrEmpty(waypoint.Action))
{
@@ -69,6 +77,8 @@ public class PathExecutor(CancellationTokenSource cts)
{
// 不管咋样,松开所有按键
Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_E);
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_SHIFT);
Simulation.SendInput.Mouse.RightButtonUp();
}
}
@@ -112,107 +122,116 @@ public class PathExecutor(CancellationTokenSource cts)
private async Task MoveTo(Waypoint waypoint)
{
+ Logger.LogInformation("粗略接近路径点,位置({x2},{y2})", $"{waypoint.X:F1}", $"{waypoint.Y:F1}");
var screen = CaptureToRectArea();
var position = Navigation.GetPosition(screen);
var targetOrientation = Navigation.GetTargetOrientation(waypoint, position);
- Logger.LogInformation("粗略接近途经点,位置({x2},{y2})", $"{waypoint.X:F1}", $"{waypoint.Y:F1}");
await _rotateTask.WaitUntilRotatedTo(targetOrientation, 5);
+
+ var hasCharacter = false;
+ // TODO 增加识别角色并切换的逻辑
+ // 可以考虑放到游泳,攀爬,等移动逻辑中
+
var startTime = DateTime.UtcNow;
var lastPositionRecord = DateTime.UtcNow;
- var fastMode = false;
var prevPositions = new List();
- // 按下w,一直走
- Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+ // 新增逻辑:普通向前移动,疾跑向前移动,飞行向前移动,游泳向前移动,攀爬向前移动,角色技能向前移动,脱离卡死
+ // NormalForward
+ // SprintForward
+ // FlightForward
+ // SwimmingForward
+ // ClimbForward
+ // CharacterSkillForward
+ // GetOutOfTheJam
+
while (!cts.IsCancellationRequested)
{
- var now = DateTime.UtcNow;
- if ((now - startTime).TotalSeconds > 60)
- {
- Logger.LogWarning("执行超时,跳过路径点");
- break;
- }
screen = CaptureToRectArea();
position = Navigation.GetPosition(screen);
var distance = Navigation.GetDistance(waypoint, position);
- Debug.WriteLine($"接近目标点中,距离为{distance}");
- if (distance < 4)
+ if (distance < 5)
{
- Logger.LogInformation("到达路径点附近");
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_E);
+ Logger.LogInformation("已到达路径点附近");
break;
}
+ // TODO 异常情况直接放到一个函数中处理,然后退出
+ // 超时
+ if (IsTimedOut(startTime))
+ {
+ Logger.LogWarning("执行超时,跳过路径点");
+ SkipWaypoint = true;
+ break;
+ }
+ // 距离终止判断
if (distance > 500)
{
Logger.LogWarning("距离过远,跳过路径点");
+ SkipWaypoint = true;
break;
}
- if ((now - lastPositionRecord).TotalMilliseconds > 1000)
+ // 卡死
+ // TODO 攀爬时应该跳过,但是如何处理看似是walk,实际是攀爬的
+ if (IsStuck(prevPositions, position, lastPositionRecord))
{
- lastPositionRecord = now;
- prevPositions.Add(position);
- if (prevPositions.Count > 8)
- {
- var delta = prevPositions[^1] - prevPositions[^8];
- if (Math.Abs(delta.X) + Math.Abs(delta.Y) < 3)
- {
- Logger.LogWarning("疑似卡死,尝试脱离并跳过路径点");
- Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
- await Delay(1500, cts);
- Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X);
- await Delay(500, cts);
- Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_S);
- await Delay(1500, cts);
- Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_A);
- await Delay(1500, cts);
- Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_D);
- await Delay(500, cts);
- return;
- }
- }
+ lastPositionRecord = DateTime.UtcNow;
+ // 脱离卡死
+ await GetOutOfTheJam();
+ SkipWaypoint = true;
+ break;
}
+ Logger.LogInformation($"接近目标点中3,距离为{distance}");
// 旋转视角
targetOrientation = Navigation.GetTargetOrientation(waypoint, position);
- _rotateTask.RotateToApproach(targetOrientation, screen);
- // 根据指定方式进行移动
+ await _rotateTask.WaitUntilRotatedTo(targetOrientation, 5);
+ // 根据移动模式选择相应的行为
if (waypoint.MoveMode == MoveModeEnum.Fly.Code)
{
- var isFlying = Bv.GetMotionStatus(screen) == MotionStatus.Fly;
- if (!isFlying)
- {
- Debug.WriteLine("未进入飞行状态,按下空格");
- Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
- await Delay(200, cts);
- }
- continue;
+ await FlightForward();
+ await Delay(1000, cts);
}
- // if (isFlying)
- // {
- // Simulation.SendInput.Mouse.LeftButtonClick();
- // await Delay(1000, cts);
- // continue;
- // }
+
if (waypoint.MoveMode == MoveModeEnum.Jump.Code)
{
- Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
- await Delay(200, cts);
- continue;
+ ClimbForward();
+ await Delay(1000, cts);
}
- // 跑步或者游泳
- if (distance > 20 != fastMode)// 距离大于20时可以使用疾跑/自由泳
+
+ if (waypoint.MoveMode == MoveModeEnum.Swim.Code)
{
- if (fastMode)
+ SwimmingForward();
+ await Delay(1000, cts);
+ }
+
+
+ if (waypoint.MoveMode == MoveModeEnum.Walk.Code)
+ {
+
+ if (distance >= 20)
{
- Simulation.SendInput.Mouse.RightButtonUp();
+ if (hasCharacter)
+ {
+ CharacterSkillForward();
+ await Delay(200, cts);
+ }
+ else
+ {
+ SprintForward();
+ await Delay(500, cts);
+ }
}
else
{
- Simulation.SendInput.Mouse.RightButtonDown();
+ // 结束e技能
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_E);
+ NormalForward();
+ await Delay(600, cts);
}
- fastMode = !fastMode;
}
- await Delay(100, cts);
+
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_SHIFT);
}
- // 抬起w键
- Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
}
private async Task MoveCloseTo(Waypoint waypoint)
@@ -276,4 +295,119 @@ public class PathExecutor(CancellationTokenSource cts)
await handler.RunAsync(cts);
}
}
+
+ // 普通向前移动
+ private void NormalForward()
+ {
+ Logger.LogInformation("正常向前移动");
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+ }
+
+ // 攀爬向前移动
+ private void ClimbForward()
+ {
+ Logger.LogInformation("进行攀爬");
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
+ // TODO 角色处理逻辑:卡其娜,西诺宁
+ }
+
+ // 疾跑向前移动
+ private void SprintForward()
+ {
+ Logger.LogInformation("疾跑向前移动");
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_SHIFT);
+ }
+
+ // 飞行向前移动
+ private async Task FlightForward()
+ {
+ Logger.LogInformation("进入飞行模式");
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+
+ var screen = CaptureToRectArea();
+ var isFlying = Bv.GetMotionStatus(screen) == MotionStatus.Fly;
+
+ if (!isFlying)
+ {
+ Logger.LogInformation("未进入飞行状态,按下空格展开翅膀");
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
+ await Delay(200, cts); // 延迟,确保飞行动作完成
+ }
+ }
+
+ // 游泳向前移动
+ private void SwimmingForward()
+ {
+ Logger.LogInformation("进入游泳模式");
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+ // TODO 添加芙宁娜处理
+ // 有芙宁娜时定时释放e技能
+ }
+
+ private void CharacterSkillForward()
+ {
+ Logger.LogInformation("使用角色技能向前移动");
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_E).Sleep(500).KeyUp(User32.VK.VK_E);
+ // TODO 根据不同角色进行处理:夜兰,闲云,散兵,早柚,玛拉妮,基尼奇
+ // 玛拉妮,散兵正常移动即可,但是夜兰,早柚是持续向前移动的,需要特殊处理
+ // 闲云,基尼奇容易超出距离,但是问题不大
+ }
+
+ // 脱离卡死
+ private async Task GetOutOfTheJam()
+ {
+ Logger.LogWarning("脱离卡死状态");
+ // 脱离攀爬状态
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
+ await Delay(1500, cts);
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X);
+ await Delay(500, cts);
+ // 向后移动
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_S);
+ await Task.Delay(1500);
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_S);
+ // 向左移动
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_A);
+ await Task.Delay(1000);
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_A);
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X);
+ await Delay(500, cts);
+ // 向右移动
+ Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_D);
+ await Task.Delay(1000);
+ Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_D);
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X);
+ await Delay(500, cts);
+ // 跳跃
+ Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
+ await Task.Delay(200); // 等待跳跃动作
+ }
+
+
+ public bool IsTimedOut(DateTime startTime)
+ {
+ var now = DateTime.UtcNow;
+ return (now - startTime).TotalSeconds > 60;
+ }
+
+ public bool IsStuck(List prevPositions, Point2f position, DateTime lastPositionRecord)
+ {
+ if ((DateTime.UtcNow - lastPositionRecord).TotalMilliseconds > 1000)
+ {
+ prevPositions.Add(position);
+ if (prevPositions.Count > 8)
+ {
+ var delta = prevPositions[^1] - prevPositions[^8];
+ if (Math.Abs(delta.X) + Math.Abs(delta.Y) < 3)
+ {
+ Logger.LogWarning("疑似卡死,尝试脱离并跳过路径点");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/Build/MicaSetup/MicaSetup.Uninst.csproj b/Build/MicaSetup/MicaSetup.Uninst.csproj
index 4e56aad1..0f08fe86 100644
--- a/Build/MicaSetup/MicaSetup.Uninst.csproj
+++ b/Build/MicaSetup/MicaSetup.Uninst.csproj
@@ -7,6 +7,7 @@
12.0
true
true
+ true
false
AnyCPU;x64
Resources\Images\FaviconUninst.ico
diff --git a/Build/MicaSetup/MicaSetup.csproj b/Build/MicaSetup/MicaSetup.csproj
index f3f367db..9a661b52 100644
--- a/Build/MicaSetup/MicaSetup.csproj
+++ b/Build/MicaSetup/MicaSetup.csproj
@@ -7,6 +7,7 @@
12.0
true
true
+ true
false
AnyCPU;x64
Resources\Images\FaviconSetup.ico
diff --git a/Fischless.GameCapture/Fischless.GameCapture.csproj b/Fischless.GameCapture/Fischless.GameCapture.csproj
index 7b895bae..d2d0f11b 100644
--- a/Fischless.GameCapture/Fischless.GameCapture.csproj
+++ b/Fischless.GameCapture/Fischless.GameCapture.csproj
@@ -6,6 +6,7 @@
enable
x64
True
+ true
True
12.0
true
diff --git a/Fischless.HotkeyCapture/Fischless.HotkeyCapture.csproj b/Fischless.HotkeyCapture/Fischless.HotkeyCapture.csproj
index bd52b9cd..33e41d6a 100644
--- a/Fischless.HotkeyCapture/Fischless.HotkeyCapture.csproj
+++ b/Fischless.HotkeyCapture/Fischless.HotkeyCapture.csproj
@@ -7,6 +7,7 @@
x64
12.0
True
+ true
True
diff --git a/Fischless.KeyboardCapture/Fischless.KeyboardCapture.csproj b/Fischless.KeyboardCapture/Fischless.KeyboardCapture.csproj
index c8eaf74b..9798cea2 100644
--- a/Fischless.KeyboardCapture/Fischless.KeyboardCapture.csproj
+++ b/Fischless.KeyboardCapture/Fischless.KeyboardCapture.csproj
@@ -6,6 +6,7 @@
enable
x64
12.0
+ true
True
diff --git a/Vision.WindowCapture.Test/Vision.WindowCapture.Test.csproj b/Vision.WindowCapture.Test/Vision.WindowCapture.Test.csproj
index e155b5f3..fe7a21f4 100644
--- a/Vision.WindowCapture.Test/Vision.WindowCapture.Test.csproj
+++ b/Vision.WindowCapture.Test/Vision.WindowCapture.Test.csproj
@@ -7,6 +7,7 @@
true
12.0
true
+ true
x64
diff --git a/Vision.WindowCapture/Vision.WindowCapture.csproj b/Vision.WindowCapture/Vision.WindowCapture.csproj
index e4ed849d..a43e2a07 100644
--- a/Vision.WindowCapture/Vision.WindowCapture.csproj
+++ b/Vision.WindowCapture/Vision.WindowCapture.csproj
@@ -5,6 +5,7 @@
enable
enable
12.0
+ true
true
x64