Merge branch 'babalae:main' into main

This commit is contained in:
FishmanTheMurloc
2025-01-25 12:05:46 +08:00
committed by GitHub
36 changed files with 938 additions and 278 deletions

View File

@@ -10,7 +10,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationIcon>Assets\Images\logo.ico</ApplicationIcon>
<AssemblyName>BetterGI</AssemblyName>
<AssemblyVersion>0.39.4</AssemblyVersion>
<AssemblyVersion>0.39.6</AssemblyVersion>
<Platforms>x64</Platforms>
<DebugType>embedded</DebugType>
</PropertyGroup>

View File

@@ -17,6 +17,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using BetterGenshinImpact.GameTask.AutoTrackPath;
namespace BetterGenshinImpact.Core.Config;
@@ -175,7 +176,11 @@ public partial class AllConfig : ObservableObject
/// 原神按键绑定配置
/// </summary>
public KeyBindingsConfig KeyBindingsConfig { get; set; } = new();
/// <summary>
/// 传送相关配置
/// </summary>
public TpConfig TpConfig { get; set; } = new();
[JsonIgnore]
public Action? OnAnyChangedAction { get; set; }
@@ -188,7 +193,6 @@ public partial class AllConfig : ObservableObject
NotificationConfig.PropertyChanged += OnAnyPropertyChanged;
NotificationConfig.PropertyChanged += OnNotificationPropertyChanged;
KeyBindingsConfig.PropertyChanged += OnAnyPropertyChanged;
AutoPickConfig.PropertyChanged += OnAnyPropertyChanged;
AutoSkipConfig.PropertyChanged += OnAnyPropertyChanged;
AutoFishingConfig.PropertyChanged += OnAnyPropertyChanged;
@@ -200,7 +204,7 @@ public partial class AllConfig : ObservableObject
AutoFightConfig.PropertyChanged += OnAnyPropertyChanged;
AutoDomainConfig.PropertyChanged += OnAnyPropertyChanged;
AutoMusicGameConfig.PropertyChanged += OnAnyPropertyChanged;
TpConfig.PropertyChanged += OnAnyPropertyChanged;
ScriptConfig.PropertyChanged += OnAnyPropertyChanged;
PathingConditionConfig.PropertyChanged += OnAnyPropertyChanged;
}

View File

@@ -32,5 +32,11 @@ public partial class CommonConfig : ObservableObject
/// 主题
/// </summary>
[ObservableProperty]
private WindowBackdropType _currentBackdropType = WindowBackdropType.Auto;
private WindowBackdropType _currentBackdropType = WindowBackdropType.Mica;
/// <summary>
/// 是否是第一次运行
/// </summary>
[ObservableProperty]
private bool _isFirstRun = true;
}

View File

@@ -436,6 +436,7 @@ public class AutoDomainTask : ISoloTask
finally
{
Logger.LogInformation("自动战斗线程结束");
combatScenes.AfterTask();
}
}, cts.Token);

View File

@@ -25,6 +25,13 @@ public partial class AutoFightConfig : ObservableObject
/// </summary>
[ObservableProperty]
private bool _fightFinishDetectEnabled = true;
/// <summary>
/// 根据技能CD优化出招人员
/// 根据填入人或人和cd来决定当此人元素战技cd未结束时跳过此人出招来优化战斗流程可填入人名或人名数字用逗号分隔
/// 多种用分号分隔,例如:白术;钟离,12;如果人名则用内置cd检查如果是人名和数字则把数字当做出招cd(秒)。
/// </summary>
[ObservableProperty] private string _actionSchedulerByCd = "";
[Serializable]
public partial class FightFinishDetectConfig : ObservableObject
{
@@ -72,6 +79,40 @@ public partial class AutoFightConfig : ObservableObject
[ObservableProperty]
private bool _pickDropsAfterFightEnabled = true;
[Serializable]
public partial class PickDropsAfterFightConfig : ObservableObject
{
/// <summary>
/// 前进次数
/// </summary>
[ObservableProperty]
private int _forwardTimes = 6;
/// <summary>
/// 校准次数
/// </summary>
[ObservableProperty]
private int _calibrationTimes = 15;
/// <summary>
/// 衰减因子
/// </summary>
[ObservableProperty]
private double _decayFactor = 0.7;
/// <summary>
/// 前进量设置为0时在[1,3]中随机
/// </summary>
[ObservableProperty]
private int _forwardSeconds = 2;
}
/// <summary>
/// 掉落寻物相关配置
/// </summary>
[ObservableProperty]
private PickDropsAfterFightConfig _pickDropsConfig = new();
/// <summary>
/// 战斗结束后,如果存在枫原万叶,则使用该角色捡材料
/// </summary>

View File

@@ -26,6 +26,7 @@ public class AutoFightParam : BaseTaskParam
FightFinishDetectEnabled = autoFightConfig.FightFinishDetectEnabled;
PickDropsAfterFightEnabled = autoFightConfig.PickDropsAfterFightEnabled;
KazuhaPickupEnabled = autoFightConfig.KazuhaPickupEnabled;
ActionSchedulerByCd = autoFightConfig.ActionSchedulerByCd;
FinishDetectConfig.FastCheckEnabled = autoFightConfig.FinishDetectConfig.FastCheckEnabled;
FinishDetectConfig.FastCheckParams = autoFightConfig.FinishDetectConfig.FastCheckParams;
@@ -47,6 +48,7 @@ public class AutoFightParam : BaseTaskParam
public int Timeout { get; set; } = 120;
public bool KazuhaPickupEnabled = true;
public string ActionSchedulerByCd = "";
}

View File

@@ -202,6 +202,7 @@ public class AutoFightTask : ISoloTask
throw new Exception("识别队伍角色失败");
}
var actionSchedulerByCd = ParseStringToDictionary(_taskParam.ActionSchedulerByCd);
var combatCommands = _combatScriptBag.FindCombatScript(combatScenes.Avatars);
// 新的取消token
@@ -221,7 +222,8 @@ public class AutoFightTask : ISoloTask
return;
}*/
var fightEndFlag = false;
string lastFighttName = "";
string lastFightName = "";
string skipFightName = "";
//统计切换人打架次数
var countFight = 0;
// 战斗操作
@@ -242,6 +244,30 @@ public class AutoFightTask : ISoloTask
break;
}
//根据元素技能冷却事件优化出招流程,只有当人物切换后才会触发检查
double skillCd;
if (lastFightName != command.Name && actionSchedulerByCd.TryGetValue(command.Name,out skillCd))
{
var avatar = combatScenes.Avatars.FirstOrDefault(a => a.Name == command.Name);
if (skillCd < 0)
{
skillCd = FindMax([avatar.SkillCd,avatar.SkillHoldCd]);
}
var dif=(DateTime.UtcNow - avatar.LastSkillTime);
//当技能未冷却时,跳过此次出招
if ((DateTime.UtcNow -avatar.LastSkillTime).TotalSeconds < skillCd)
{
if (skipFightName != command.Name)
{
Logger.LogInformation($"{command.Name}cd冷却为{skillCd}秒,剩余{skillCd-dif.TotalSeconds}秒,跳过此次行动");
}
skipFightName = command.Name;
continue;
}
}
command.Execute(combatScenes);
//统计战斗人次
if (i == combatCommands.Count - 1 || command.Name != combatCommands[i + 1].Name)
@@ -249,7 +275,7 @@ public class AutoFightTask : ISoloTask
countFight++;
}
lastFighttName = command.Name;
lastFightName = command.Name;
if (!fightEndFlag && _taskParam is { FightFinishDetectEnabled: true })
{
//处于最后一个位置,或者当前执行人和下一个人名字不一样的情况,满足一定条件(开启快速检查并且检查时间大于0或人名存在配置)检查战斗
@@ -341,7 +367,7 @@ public class AutoFightTask : ISoloTask
{
var time = DateTime.UtcNow - kazuha.LastSkillTime;
//当万叶cd大于3时或战斗人次少于2时通常无怪物情况下此时不再触发万叶拾取
if (!(countFight < 2 || lastFighttName == "枫原万叶" && time.TotalSeconds > 3))
if (!(countFight < 2 || lastFightName == "枫原万叶" && time.TotalSeconds > 3))
{
Logger.LogInformation("使用枫原万叶长E拾取掉落物");
await Delay(300, ct);
@@ -470,6 +496,53 @@ public class AutoFightTask : ISoloTask
(g >= 240 && g <= 255) &&
(b >= 240 && b <= 255);
}
static double FindMax(double[] numbers)
{
if (numbers == null || numbers.Length == 0)
{
throw new ArgumentException("The array is empty or null.");
}
double max = numbers[0]>10000 ? 0 : numbers[0];
foreach (var num in numbers)
{
var cpnum = numbers[0]>10000 ? 0 : num;
max = Math.Max(max, num);
}
return max;
}
private static Dictionary<string, double> ParseStringToDictionary(string input,double defaultValue=-1)
{
var dictionary = new Dictionary<string, double>();
if (string.IsNullOrEmpty(input))
{
return dictionary; // 返回空字典
}
string[] pairs = input.Split(';', StringSplitOptions.RemoveEmptyEntries);
foreach (var pair in pairs)
{
var parts = pair.Split(',', StringSplitOptions.TrimEntries);
if (parts.Length > 0)
{
string name = parts[0];
double value = defaultValue;
if (parts.Length > 1 && double.TryParse(parts[1], out var parsedValue))
{
value = parsedValue;
}
dictionary[name] = value;
}
}
return dictionary;
}
private bool HasFightFlagByYolo(ImageRegion imageRegion)
{

View File

@@ -31,7 +31,7 @@ public class CombatScenes : IDisposable
/// <summary>
/// 当前配队
/// </summary>
public Avatar[] Avatars { get; set; } = Array.Empty<Avatar>();
public Avatar[] Avatars { get; set; } = [];
public Dictionary<string, Avatar> AvatarMap { get; set; } = [];
@@ -70,6 +70,7 @@ public class CombatScenes : IDisposable
{
throw new Exception("当前处于联机状态但是队伍人数超过4人无法识别");
}
// 联机状态下判断
var onePRa = imageRegion.Find(AutoFightAssets.Instance.OnePRa);
var p = "p";
@@ -167,7 +168,7 @@ public class CombatScenes : IDisposable
if (result.TopClass.Confidence < 0.51)
{
Cv2.ImWrite(@"log\avatar_side_classify_error.png", src.ToMat());
throw new Exception($"无法识别第{index}位角色,置信度{result.TopClass.Confidence:F1},结果:{result.TopClass.Name.Name}。请确认您是否阅读了文档中的《快速上手》!");
throw new Exception($"无法识别第{index}位角色,置信度{result.TopClass.Confidence:F1},结果:{result.TopClass.Name.Name}。请重新阅读了文档中的《快速上手》!");
}
}
else
@@ -175,7 +176,7 @@ public class CombatScenes : IDisposable
if (result.TopClass.Confidence < 0.7)
{
Cv2.ImWrite(@"log\avatar_side_classify_error.png", src.ToMat());
throw new Exception($"无法识别第{index}位角色,置信度{result.TopClass.Confidence:F1},结果:{result.TopClass.Name.Name}。请确认您是否阅读了文档中的《快速上手》!");
throw new Exception($"无法识别第{index}位角色,置信度{result.TopClass.Confidence:F1},结果:{result.TopClass.Name.Name}。请重新阅读了文档中的《快速上手》!");
}
}
@@ -246,6 +247,21 @@ public class CombatScenes : IDisposable
}
}
public void AfterTask()
{
var mwk = SelectAvatar("玛薇卡");
if (mwk != null)
{
foreach (var avatar in Avatars)
{
if (avatar.Name != "玛薇卡")
{
avatar.Switch();
}
}
}
}
public Avatar? SelectAvatar(string name)
{
return AvatarMap.GetValueOrDefault(name);
@@ -381,4 +397,4 @@ public class CombatScenes : IDisposable
{
_predictor.Dispose();
}
}
}

View File

@@ -1,5 +1,7 @@
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.GameTask.Common;
using Microsoft.Extensions.Logging;
namespace BetterGenshinImpact.GameTask.AutoGeniusInvokation;
@@ -9,9 +11,17 @@ public class AutoGeniusInvokationTask(GeniusInvokationTaskParam taskParam) : ISo
public Task Start(CancellationToken ct)
{
// 读取策略信息
var duel = ScriptParser.Parse(taskParam.StrategyContent);
duel.Run(ct);
try
{
// 读取策略信息
var duel = ScriptParser.Parse(taskParam.StrategyContent);
duel.Run(ct);
}
catch (System.Exception e)
{
TaskControl.Logger.LogDebug(e, "执行自动七圣召唤任务异常");
TaskControl.Logger.LogError("执行自动七圣召唤任务异常:{Exception}", e.Message);
}
return Task.CompletedTask;
}
}
}

View File

@@ -117,7 +117,7 @@ public class ScriptParser
var characterAndSkill = line.Split('{');
var parts = characterAndSkill[0].Split('=');
character.Index = int.Parse(RegexHelper.ExcludeNumberRegex().Replace(parts[0], ""));
character.Index = int.Parse(RegexHelper.ExcludeNumberRegex().Replace(parts[0].Trim(), ""));
MyAssert(character.Index >= 1 && character.Index <= 3, "角色序号必须在1-3之间");
if (parts[1].Contains('|'))

View File

@@ -6,6 +6,7 @@ public class MoveModeEnum(string code, string msg)
{
public static readonly MoveModeEnum Walk = new("walk", "步行");
public static readonly MoveModeEnum Run = new("run", "奔跑");
public static readonly MoveModeEnum Dash = new("dash", "持续冲刺");
public static readonly MoveModeEnum Climb = new("climb", "攀爬");
public static readonly MoveModeEnum Fly = new("fly", "飞行");
public static readonly MoveModeEnum Jump = new("jump", "跳跃");

View File

@@ -680,7 +680,23 @@ public class PathExecutor
// 只有设置为run才会一直疾跑
if (waypoint.MoveMode == MoveModeEnum.Run.Code)
{
if (distance > 25) // 距离大于25时可以使用疾跑
if (distance > 20 != fastMode) // 距离大于20时可以使用疾跑/自由泳
{
if (fastMode)
{
Simulation.SendInput.SimulateAction(GIActions.SprintMouse, KeyType.KeyUp);
}
else
{
Simulation.SendInput.SimulateAction(GIActions.SprintMouse, KeyType.KeyDown);
}
fastMode = !fastMode;
}
}
else if (waypoint.MoveMode == MoveModeEnum.Dash.Code)
{
if (distance > 20) // 距离大于25时可以使用疾跑
{
if (Math.Abs((fastModeColdTime - DateTime.UtcNow).TotalMilliseconds) > 1000) //冷却一会
{

View File

@@ -41,25 +41,25 @@
"我带凯亚去没去过的地方玩吧"
],
"卡维结局1:未来蓝图": [
"一起去说服委托人吧",
"一起去说服刚刚的委托人吧",
"尝试一下新的风格"
],
"卡维结局2:契约达成": [
"一起去说服委托人吧",
"一起去说服刚刚的委托人吧",
"可以找其他商人筹款"
],
"卡维结局3:闲时小聚": [
"做些别的事转心情",
"做些别的事转心情",
"卡维为什么要当设计师呢",
"去找熟人问问"
],
"卡维结局4:群星之下": [
"做些别的事转心情",
"做些别的事转心情",
"卡维为什么要当设计师呢",
"还是先别管这个了"
],
"卡维结局5:第1堂课": [
"做些别的事转心情",
"做些别的事转心情",
"找份其他工作赚钱"
],
"莱依拉结局1:不可说之事": [
@@ -74,7 +74,7 @@
"莱依拉结局2:代价与回报": [
"虽然有些不靠谱",
"我陪你去找答案",
"仙灵应该不想苛责你"
"仙灵应该不只是想苛责你"
],
"莱依拉结局3:不愿重蹈覆辙": [
"虽然有些不靠谱",

View File

@@ -0,0 +1,55 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
namespace BetterGenshinImpact.GameTask.AutoTrackPath;
public partial class TpConfig : ObservableObject
{
[ObservableProperty]
private bool _mapZoomEnabled = true; // 地图缩放开关
[ObservableProperty]
private int _mapZoomOutDistance = 2000; // 地图缩小的最小距离,单位:像素
[ObservableProperty]
private int _mapZoomInDistance = 400; // 地图放大的最大距离,单位:像素
[ObservableProperty]
private int _stepIntervalMilliseconds = 20; // 鼠标移动时间间隔单位ms
[ObservableProperty]
private double _maxZoomLevel = 5.0; // 最大缩放等级
[ObservableProperty]
private double _minZoomLevel = 1.7; // 最小缩放等级
[ObservableProperty]
private double _reviveStatueOfTheSevenPointX = 2296.4; // 七天神像点位X坐标
[ObservableProperty]
private double _reviveStatueOfTheSevenPointY = -824.4; // 七天神像点位Y坐标
[ObservableProperty]
private int _zoomOutButtonY = 654; // y-coordinate for zoom-out button
[ObservableProperty]
private int _zoomInButtonY = 428; // y-coordinate for zoom-in button
[ObservableProperty]
private int _zoomButtonX = 49; // x-coordinate for zoom button
[ObservableProperty]
private int _zoomStartY = 453; // y-coordinate for zoom start
[ObservableProperty]
private int _zoomEndY = 628; // y-coordinate for zoom end
[ObservableProperty]
private double _tolerance = 200; // 允许的移动误差
[ObservableProperty]
private int _maxIterations = 30; // 移动最大次数
[ObservableProperty]
private int _maxMouseMove = 300; // 单次移动最大距离
}

View File

@@ -1,28 +1,26 @@
using BetterGenshinImpact.Core.Recognition;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.Core.Script.Dependence;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.Core.Simulator.Extensions;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception;
using BetterGenshinImpact.GameTask.Common;
using BetterGenshinImpact.GameTask.Common.BgiVision;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Common.Exceptions;
using BetterGenshinImpact.GameTask.Common.Map;
using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
using BetterGenshinImpact.Helpers.Extensions;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.GameTask.Common.Exceptions;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
using BetterGenshinImpact.Core.Simulator.Extensions;
using BetterGenshinImpact.GameTask.Common.Job;
using BetterGenshinImpact.Core.Script.Dependence;
using Microsoft.Diagnostics.Utilities;
namespace BetterGenshinImpact.GameTask.AutoTrackPath;
@@ -34,89 +32,17 @@ public class TpTask(CancellationToken ct)
private readonly QuickTeleportAssets _assets = QuickTeleportAssets.Instance;
private readonly Rect _captureRect = TaskContext.Instance().SystemInfo.ScaleMax1080PCaptureRect;
private readonly double _zoomOutMax1080PRatio = TaskContext.Instance().SystemInfo.ZoomOutMax1080PRatio;
private static double ReviveStatueOfTheSevenPointX = 2296.4;
private static double ReviveStatueOfTheSevenPointY = -824.4;
private static int zoomOutButtonY = 654; // y-coordinate for zoom-out button
private static int zoomInButtonY = 428; // y-coordinate for zoom-in button
private static int zoomButtonX = 49; // x-coordinate for zoom button
private static int zoomStartY = 453; // y-coordinate for zoom start
private static int zoomEndY = 628; // y-coordinate for zoom end
private static bool _mapZoomEnabled = true;
private static int _mapZoomOutDistance = 1000;
private static int _mapZoomInDistance = 400;
private static int _stepIntervalMilliseconds = 20;
public static bool MapZoomEnabled
{
get => _mapZoomEnabled;
set
{
_mapZoomEnabled = value;
if(!value)
{
Logger.LogInformation("禁用了缩放功能,请自行调整合适的缩放,部分脚本可能会因为禁用缩放功能无法使用");
}
}
}
public static int MapZoomOutDistance
{
get => _mapZoomOutDistance;
set
{
if (value < 500 || value > 5000) // 自动设置合理范围
{
_mapZoomOutDistance = 1000;
}
if (value <= _mapZoomInDistance)
{
_mapZoomOutDistance = _mapZoomInDistance * 2;
}
_mapZoomOutDistance = value;
}
}
public static int MapZoomInDistance
{
get => _mapZoomInDistance;
set
{
if (value < 200 || value > 1000) // 自动设置合理范围
{
_mapZoomInDistance = 400;
}
if (value >= _mapZoomOutDistance)
{
_mapZoomInDistance = _mapZoomOutDistance / 2;
}
_mapZoomInDistance = value;
}
}
public static int StepIntervalMilliseconds
{
get => _stepIntervalMilliseconds;
set
{
if (value < 5 || value > 100)
{
_stepIntervalMilliseconds = 20;
}
_stepIntervalMilliseconds = value;
}
}
private readonly TpConfig _tpConfig = TaskContext.Instance().Config.TpConfig;
/// <summary>
/// 传送到须弥七天神像
/// </summary>
public async Task TpToStatueOfTheSeven()
{
await CheckInBigMapUi();
if (_mapZoomEnabled)
if (_tpConfig.MapZoomEnabled)
{
double currentZoomLevel = GetBigMapZoomLevel(CaptureToRectArea());
bool tempMapZoomEnable = _mapZoomEnabled;
_mapZoomEnabled = false; // 临时禁用缩放功能
if (currentZoomLevel > 4.5)
{
await AdjustMapZoomLevel(currentZoomLevel, 4.5);
@@ -125,13 +51,8 @@ public class TpTask(CancellationToken ct)
{
await AdjustMapZoomLevel(currentZoomLevel, 3);
}
await Tp(ReviveStatueOfTheSevenPointX, ReviveStatueOfTheSevenPointY);
_mapZoomEnabled = tempMapZoomEnable;
}
else
{
await Tp(ReviveStatueOfTheSevenPointX, ReviveStatueOfTheSevenPointY);
}
await Tp(_tpConfig.ReviveStatueOfTheSevenPointX, _tpConfig.ReviveStatueOfTheSevenPointY);
}
/// <summary>
/// 通过大地图传送到指定坐标最近的传送点,然后移动到指定坐标
@@ -139,9 +60,10 @@ public class TpTask(CancellationToken ct)
/// <param name="tpX"></param>
/// <param name="tpY"></param>
/// <param name="force">强制以当前的tpX,tpY坐标进行自动传送</param>
public async Task<(double, double)> TpOnce(double tpX, double tpY, bool force = false)
private async Task<(double, double)> TpOnce(double tpX, double tpY, bool force = false)
{
var (x, y) = (tpX, tpY);
string? country = null;
if (!force)
{
@@ -152,25 +74,23 @@ public class TpTask(CancellationToken ct)
// 计算传送点位置离哪个地图切换后的中心点最近,切换到该地图
await SwitchRecentlyCountryMap(x, y, country);
// 计算坐标后点击
var bigMapInAllMapRect = GetBigMapRect();
if (_mapZoomEnabled)
if (_tpConfig.MapZoomEnabled)
{
double zoomLevel = GetBigMapZoomLevel(CaptureToRectArea());
if (zoomLevel > 4.5)
{
// 显示传送锚点和秘境的缩放等级
await AdjustMapZoomLevel(zoomLevel, 4.5);
Logger.LogInformation("当前缩放等级过大,调整为 {zoomLevel:0.000}", 4.5);
Logger.LogInformation("当前缩放等级过大,调整为 {zoomLevel:0.00}", 4.5);
}
}
var bigMapInAllMapRect = GetBigMapRect();
while (!IsPointInBigMapWindow(bigMapInAllMapRect, x, y)) // 左上角 350x400也属于禁止点击区域
{
Debug.WriteLine($"({x},{y}) 不在 {bigMapInAllMapRect} 内,继续移动");
Logger.LogInformation("传送点不在当前大地图范围内,继续移动");
await MoveMapTo(x, y, maxMouseMove: 400);
await MoveMapTo(x, y);
await Delay(300, ct); // 等待地图移动完成
bigMapInAllMapRect = GetBigMapRect();
}
@@ -318,10 +238,8 @@ public class TpTask(CancellationToken ct)
/// </summary>
/// <param name="x">目标x坐标</param>
/// <param name="y">目标y坐标</param>
/// <param name="tolerance">允许误差默认200</param>
/// <param name="maxIterations">最大尝试次数默认30</param>
/// <param name="maxMouseMove">单次移动最大距离默认250</param>
public async Task MoveMapTo(double x, double y, double tolerance = 200, int maxIterations = 30, int maxMouseMove = 250)
private async Task MoveMapTo(double x, double y)
{
// 获取当前地图中心点并计算到目标传送点的初始偏移
// await AdjustMapZoomLevel(mapZoomLevel);
@@ -333,7 +251,7 @@ public class TpTask(CancellationToken ct)
int moveSteps = 10;
double totalMoveMouseX = Double.MaxValue;
double totalMoveMouseY = Double.MaxValue;
for (int iteration = 0; iteration < maxIterations; iteration++)
for (int iteration = 0; iteration < _tpConfig.MaxIterations; iteration++)
{
// 尝试移动鼠标
await MouseMoveMap(moveMouseX, moveMouseY, moveSteps);
@@ -363,20 +281,22 @@ public class TpTask(CancellationToken ct)
totalMoveMouseY = Math.Abs(moveMouseY * yOffset / diffMapY);
double mouseDistance = Math.Sqrt(totalMoveMouseX * totalMoveMouseX + totalMoveMouseY * totalMoveMouseY);
if (_mapZoomEnabled)
if (_tpConfig.MapZoomEnabled)
{
// 调整地图缩放
// mapZoomLevel<5 才显示传送锚点和秘境; mapZoomLevel>1.7 可以避免点错传送锚点
double currentZoomLevel = GetBigMapZoomLevel(CaptureToRectArea());
double oldZoomLevel = currentZoomLevel;
while (mouseDistance > MapZoomOutDistance || mouseDistance < MapZoomInDistance)
while (mouseDistance > _tpConfig.MapZoomOutDistance || mouseDistance < _tpConfig.MapZoomInDistance)
{
bool zoomOut = mouseDistance > MapZoomOutDistance;
bool zoomIn = mouseDistance < MapZoomInDistance;
if (zoomOut && currentZoomLevel < 4.0 || zoomIn && currentZoomLevel > 2.7)
bool zoomOut = mouseDistance > _tpConfig.MapZoomOutDistance;
bool zoomIn = mouseDistance < _tpConfig.MapZoomInDistance;
if (zoomOut && currentZoomLevel < _tpConfig.MaxZoomLevel - 1.0
|| zoomIn && currentZoomLevel > _tpConfig.MinZoomLevel + 1.0)
{
await AdjustMapZoomLevel(zoomIn);
await Delay(50, ct);
currentZoomLevel = GetBigMapZoomLevel(CaptureToRectArea());
totalMoveMouseX *= oldZoomLevel / currentZoomLevel;
totalMoveMouseY *= oldZoomLevel / currentZoomLevel;
@@ -385,9 +305,9 @@ public class TpTask(CancellationToken ct)
}
else
{
double targetZoom = zoomIn ? 1.7 : 5.0;
double targetZoom = zoomIn ? _tpConfig.MinZoomLevel : _tpConfig.MaxZoomLevel;
// 考虑调整和识别误差所以相差0.05就不再调整。
if (currentZoomLevel > 4.95 || currentZoomLevel < 1.75)
if (currentZoomLevel > _tpConfig.MaxZoomLevel - 0.05 || currentZoomLevel < _tpConfig.MinZoomLevel + 0.05)
{
break;
}
@@ -398,21 +318,20 @@ public class TpTask(CancellationToken ct)
}
// 非常接近目标点,不再进一步调整
if (mouseDistance < tolerance)
if (mouseDistance < _tpConfig.Tolerance)
{
Logger.LogInformation("移动 {I} 次鼠标后,已经接近目标点,不再移动地图。", iteration + 1);
break;
}
// 单次移动最大距离为 maxMouseMove
moveMouseX = (int)Math.Min(totalMoveMouseX, maxMouseMove * totalMoveMouseX / mouseDistance) * Math.Sign(xOffset);
moveMouseY = (int)Math.Min(totalMoveMouseY, maxMouseMove * totalMoveMouseY / mouseDistance) * Math.Sign(yOffset);
moveMouseX = (int)Math.Min(totalMoveMouseX, _tpConfig.MaxMouseMove * totalMoveMouseX / mouseDistance) * Math.Sign(xOffset);
moveMouseY = (int)Math.Min(totalMoveMouseY, _tpConfig.MaxMouseMove * totalMoveMouseY / mouseDistance) * Math.Sign(yOffset);
double moveMouseLength = Math.Sqrt(moveMouseX * moveMouseX + moveMouseY * moveMouseY);
moveSteps = Math.Max((int)moveMouseLength / 10, 3); // 每次移动的步数最小为3避免除0错误
}
else
{
Logger.LogDebug($"第 {iteration} 次移动鼠标失败,可能是点击了传送点或者其他交互对象。");
Logger.LogDebug($"第 {iteration + 1} 次移动鼠标失败,可能是点击了传送点或者其他交互对象。");
}
}
}
@@ -440,25 +359,26 @@ public class TpTask(CancellationToken ct)
/// 调整地图缩放级别以加速移动
/// </summary>
/// <param name="zoomIn">是否放大地图</param>
public async Task AdjustMapZoomLevel(bool zoomIn)
private async Task AdjustMapZoomLevel(bool zoomIn)
{
if (zoomIn)
{
GameCaptureRegion.GameRegionClick((rect, scale) => (zoomButtonX * scale, zoomInButtonY * scale));
GameCaptureRegion.GameRegionClick((rect, scale) => (_tpConfig.ZoomButtonX * scale, _tpConfig.ZoomInButtonY * scale));
}
else
{
GameCaptureRegion.GameRegionClick((rect, scale) => (zoomButtonX * scale, zoomOutButtonY * scale));
GameCaptureRegion.GameRegionClick((rect, scale) => (_tpConfig.ZoomButtonX * scale, _tpConfig.ZoomOutButtonY * scale));
}
await Delay(50, ct);
}
[Obsolete]
/// <summary>
/// 调整地图的缩放等级(整数缩放级别)。
/// </summary>
/// <param name="zoomLevel">目标等级1-6。整数。随着数字变大地图越小细节越少。</param>
[Obsolete]
public async Task AdjustMapZoomLevel(int zoomLevel)
{
for (int i = 0; i < 5; i++)
@@ -478,15 +398,15 @@ public class TpTask(CancellationToken ct)
/// </summary>
/// <param name="zoomLevel">当前缩放等级1.0-6.0,浮点数。</param>
/// <param name="targetZoomLevel">目标缩放等级1.0-6.0,浮点数。</param>
public async Task AdjustMapZoomLevel(double zoomLevel, double targetZoomLevel)
private async Task AdjustMapZoomLevel(double zoomLevel, double targetZoomLevel)
{
// Logger.LogInformation("调整地图缩放等级:{zoomLevel:0.000} -> {targetZoomLevel:0.000}", zoomLevel, targetZoomLevel);
int initialY = (int)(zoomStartY + (zoomEndY - zoomStartY) * (zoomLevel - 1) / 5d);
int targetY = (int)(zoomStartY + (zoomEndY - zoomStartY) * (targetZoomLevel - 1) / 5d);
await MouseClickAndMove(zoomButtonX, initialY, zoomButtonX, targetY);
int initialY = (int)(_tpConfig.ZoomStartY + (_tpConfig.ZoomEndY - _tpConfig.ZoomStartY) * (zoomLevel - 1) / 5d);
int targetY = (int)(_tpConfig.ZoomStartY + (_tpConfig.ZoomEndY - _tpConfig.ZoomStartY) * (targetZoomLevel - 1) / 5d);
await MouseClickAndMove(_tpConfig.ZoomButtonX, initialY, _tpConfig.ZoomButtonX, targetY);
}
public async Task MouseMoveMap(int pixelDeltaX, int pixelDeltaY, int steps = 10)
private async Task MouseMoveMap(int pixelDeltaX, int pixelDeltaY, int steps = 10)
{
// 确保不影响总移动距离
int totalX = 0;
@@ -506,8 +426,8 @@ public class TpTask(CancellationToken ct)
}
// 均匀分配多余的部分到前半段
int remainingX = (int)(pixelDeltaX - totalX);
int remainingY = (int)(pixelDeltaY - totalY);
int remainingX = (pixelDeltaX - totalX);
int remainingY = (pixelDeltaY - totalY);
for (int i = 0; i < steps / 2 + 1; i++)
{
stepX[i] += remainingX / (steps / 2 + 1) + ((remainingX % (steps / 2 + 1) > i) ? 0 : 1);
@@ -523,7 +443,7 @@ public class TpTask(CancellationToken ct)
for (var i = 0; i < steps; i++)
{
GlobalMethod.MoveMouseBy(stepX[i], stepY[i]);
await Delay(StepIntervalMilliseconds, ct);
await Delay(_tpConfig.StepIntervalMilliseconds, ct);
}
GlobalMethod.LeftButtonUp();
}
@@ -604,7 +524,7 @@ public class TpTask(CancellationToken ct)
}
/// <summary>
/// 获取最近的传送点位置
/// 获取最近的传送点位置和所处区域
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
@@ -820,4 +740,4 @@ public class TpTask(CancellationToken ct)
// 1~6 的缩放等级
return (-5 * s) + 6;
}
}
}

View File

@@ -16,6 +16,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Simulator.Extensions;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
using static Vanara.PInvoke.User32;
@@ -30,7 +31,7 @@ public partial class AutoWoodTask : ISoloTask
{
public string Name => "自动伐木";
private readonly AutoWoodAssets _assets;
private AutoWoodAssets _assets;
private bool _first = true;
@@ -38,7 +39,7 @@ public partial class AutoWoodTask : ISoloTask
private readonly Login3rdParty _login3rdParty;
private VK _zKey = VK.VK_Z;
// private VK _zKey = VK.VK_Z;
private readonly WoodTaskParam _taskParam;
@@ -49,12 +50,13 @@ public partial class AutoWoodTask : ISoloTask
this._taskParam = taskParam;
_login3rdParty = new();
AutoWoodAssets.DestroyInstance();
_assets = AutoWoodAssets.Instance;
_printer = new WoodStatisticsPrinter(_assets);
}
public Task Start(CancellationToken ct)
{
_assets = AutoWoodAssets.Instance;
var runTimeWatch = new Stopwatch();
_ct = ct;
_printer.Ct = _ct;
@@ -70,20 +72,20 @@ public partial class AutoWoodTask : ISoloTask
Logger.LogInformation("自动伐木启用B服模式");
}
SettingsContainer settingsContainer = new();
if (settingsContainer.OverrideController?.KeyboardMap?.ActionElementMap.Where(item => item.ActionId == ActionId.Gadget).FirstOrDefault()?.ElementIdentifierId is ElementIdentifierId key)
{
if (key != ElementIdentifierId.Z)
{
_zKey = key.ToVK();
Logger.LogInformation($"自动伐木检测到用户改键 {ElementIdentifierId.Z.ToName()} 改为 {key.ToName()}");
if (key == ElementIdentifierId.LeftShift || key == ElementIdentifierId.RightShift)
{
Logger.LogInformation($"用户改键 {key.ToName()} 可能不受模拟支持,若使用正常则忽略");
}
}
}
// SettingsContainer settingsContainer = new();
//
// if (settingsContainer.OverrideController?.KeyboardMap?.ActionElementMap.Where(item => item.ActionId == ActionId.Gadget).FirstOrDefault()?.ElementIdentifierId is ElementIdentifierId key)
// {
// if (key != ElementIdentifierId.Z)
// {
// _zKey = key.ToVK();
// Logger.LogInformation($"自动伐木检测到用户改键 {ElementIdentifierId.Z.ToName()} 改为 {key.ToName()}");
// if (key == ElementIdentifierId.LeftShift || key == ElementIdentifierId.RightShift)
// {
// Logger.LogInformation($"用户改键 {key.ToName()} 可能不受模拟支持,若使用正常则忽略");
// }
// }
// }
SystemControl.ActivateWindow();
// 伐木开始计时
@@ -168,6 +170,7 @@ public partial class AutoWoodTask : ISoloTask
TaskContext.Instance().Config.AutoWoodConfig.WoodCountOcrEnabled = false;
throw new NormalEndException("首次伐木就未识别到木材数据已经自动关闭【OCR识别并累计木材数】的功能请重新启动【自动伐木】功能");
}
return;
}
@@ -210,6 +213,7 @@ public partial class AutoWoodTask : ISoloTask
return _firstWoodOcrText;
}
}
stopwatch.Stop(); // 停止计时
_firstWoodOcrText = FindBestOcrResult(firstOcrResultList);
return _firstWoodOcrText;
@@ -234,6 +238,7 @@ public partial class AutoWoodTask : ISoloTask
return !string.IsNullOrEmpty(recognizedText) &&
recognizedText.Contains("获得");
}
return !string.IsNullOrEmpty(recognizedText) &&
recognizedText.Contains("获得") &&
(recognizedText.Contains('×') || recognizedText.Contains('x'));
@@ -291,6 +296,7 @@ public partial class AutoWoodTask : ISoloTask
Logger.LogWarning("未知的木材名:{woodName},数量{Cnt}", materialName, quantity);
return;
}
WoodTotalDict.AddOrUpdate(
key: materialName,
addValue: quantity,
@@ -334,6 +340,7 @@ public partial class AutoWoodTask : ISoloTask
isFound = false;
continue;
}
var materialName = match.Groups[1].Value.Trim();
Debug.WriteLine($"第一次获取的木材名称:{materialName}");
if (!ExistWoods.Contains(materialName))
@@ -417,14 +424,14 @@ public partial class AutoWoodTask : ISoloTask
throw new NormalEndException("请先装备小道具「王树瑞佑」!");
#else
System.Threading.Thread.Sleep(2000);
Simulation.SendInput.Keyboard.KeyPress(_zKey);
Simulation.SendInput.SimulateAction(GIActions.QuickUseGadget);
Debug.WriteLine("[AutoWood] Z");
_first = false;
#endif
}
else
{
Simulation.SendInput.Keyboard.KeyPress(_zKey);
Simulation.SendInput.SimulateAction(GIActions.QuickUseGadget);
Debug.WriteLine("[AutoWood] Z");
_first = false;
}
@@ -445,7 +452,7 @@ public partial class AutoWoodTask : ISoloTask
#endif
}
Simulation.SendInput.Keyboard.KeyPress(_zKey);
Simulation.SendInput.SimulateAction(GIActions.QuickUseGadget);
Debug.WriteLine("[AutoWood] Z");
Sleep(500, _ct);
}, TimeSpan.FromSeconds(1), 120);
@@ -542,4 +549,4 @@ public partial class AutoWoodTask : ISoloTask
throw new RetryException("未检测进入游戏界面");
}
}
}
}

View File

@@ -31,14 +31,14 @@ public class GoToAdventurersGuildTask
{
try
{
// 合成完毕后领取奖励
await new ClaimEncounterPointsRewardsTask().Start(ct);
// 如果有好感队伍名称,先切换到好感队伍
if (!string.IsNullOrEmpty(dailyRewardPartyName))
{
await new SwitchPartyTask().Start(dailyRewardPartyName, ct);
}
// F1领取奖励
await new ClaimEncounterPointsRewardsTask().Start(ct);
await DoOnce(country, ct);
break;

View File

@@ -44,13 +44,15 @@ public class ScanPickTask
public async Task DoOnce(CancellationToken ct)
{
await ResetCamera(ct);
for (int n = 0; n < 5; n++) // 最多跑5次
var forwardTimes = TaskContext.Instance().Config.AutoFightConfig.PickDropsConfig.ForwardTimes;
for (int n = 0; n < forwardTimes; n++) // 直走次数
{
await ResetCamera(ct);
var hasDrops = false;
// 旋转视角
var step = 300 * _dpi; // TODO:把300换成一个更加普适的值
step = n % 2 == 0 ? step : -step;
for (var i = 0; i < 20; i++)
{
var ra = CaptureToRectArea();
@@ -63,18 +65,14 @@ public class ScanPickTask
if (pickItems.Count > 0)
{
hasDrops = true;
// 把鼠标位置和物品位置重合
MoveCursorTo(pickItems.First(), ra);
await Delay(100, ct);
// 物体越小,距离越远
await WalkForward(ct);
await MoveTowardsFirstDrop(ct, 300 * _dpi);
break;
}
Simulation.SendInput.Mouse.MoveMouseBy((int)(300 * _dpi), 0);
Simulation.SendInput.Mouse.MoveMouseBy((int)step, 0);
await Delay(100, ct);
}
if (!hasDrops)
{
break;
@@ -83,13 +81,56 @@ public class ScanPickTask
}
private static async Task WalkForward(CancellationToken ct)
private static async Task WalkForward(CancellationToken ct, int ms = 1000)
{
Simulation.SendInput.SimulateAction(GIActions.MoveForward, KeyType.KeyDown);
await Delay(1000, ct);
await Delay(ms, ct);
Simulation.SendInput.SimulateAction(GIActions.MoveForward, KeyType.KeyUp);
}
private async Task MoveTowardsFirstDrop(CancellationToken ct, double step)
{
//通过每次缩小之前的步长来定位,可能有一定开销
var decayFactor = TaskContext.Instance().Config.AutoFightConfig.PickDropsConfig.DecayFactor;
var calibrationTimes = TaskContext.Instance().Config.AutoFightConfig.PickDropsConfig.CalibrationTimes;
var found = false;
for (var i = 0; i < calibrationTimes; i++)
{
var ra = CaptureToRectArea();
var resultDic = _predictor.Detect(ra);
var pickItems = resultDic.Where(x => x.Key is "drops" or "ore")
.SelectMany(x => x.Value).ToList();
if (pickItems.Count > 0)
{
step *= decayFactor;
found = true;
//只关心横坐标
var centerX = (pickItems.First().Left + pickItems.First().Right) / 2;
var dx = centerX - ra.Width / 2;
if (dx > 0)
Simulation.SendInput.Mouse.MoveMouseBy((int)step, 0);
else if (dx < 0)
Simulation.SendInput.Mouse.MoveMouseBy(-(int)step, 0);
await Delay(100, ct);
}
else
{
//也许已经对准,被人物挡住
break;
}
}
if (found) //仅在找到物品时前进(在误判进入该函数时避免远离原地)
{
Logger.LogInformation("前进采集");
var forwardms = TaskContext.Instance().Config.AutoFightConfig.PickDropsConfig.ForwardSeconds * 1000;
if (forwardms == 0)
forwardms = new Random().Next(1000, 3000);
await WalkForward(ct, forwardms);
}
}
private void MoveCursorTo(Rect item, ImageRegion ra)
{
var centerX = (item.Left + item.Right) / 2;
@@ -103,8 +144,8 @@ public class ScanPickTask
// 回正 并下移视角
private async Task ResetCamera(CancellationToken ct)
{
// Simulation.SendInput.Keyboard.Mouse.MiddleButtonClick();
// await Delay(500, ct);
Simulation.SendInput.Keyboard.Mouse.MiddleButtonClick();
await Delay(500, ct);
Simulation.SendInput.Keyboard.Mouse.MoveMouseBy(0, (int)(500 * _dpi));
await Delay(100, ct);
}

View File

@@ -325,7 +325,8 @@ namespace LogParse
(name: "最后小怪日期", value: ms => ms.LastSmallTime),
(name: "精英", value: ms => ms.EliteGameStatistics.ToString()),
(name: "精英详细", value: ms => ms.EliteDetails), (name: "最后精英日期", value: ms => ms.LastEliteTime),
(name: "总计锄地摩拉", value: ms => ms.TotalMoraKillingMonstersMora.ToString())
(name: "总计锄地摩拉", value: ms => ms.TotalMoraKillingMonstersMora.ToString()),
(name: "突发事件获取摩拉", value: ms => ms.EmergencyBonus)
];
//锄地部分新曾字段
(string name, Func<MoraStatistics, string> value)[] col2Configs=[..msColConfigs.ToList().Where(item=>item.name!="日期" && item.name!="最后小怪日期" && item.name!="最后精英日期"),
@@ -386,7 +387,7 @@ namespace LogParse
.OrderBy(group => group.Key)
.Reverse().ToList();
html.AppendLine($"<h2>按日锄地摩拉统计</h2>");
html.AppendLine($"<h2>按日摩拉收益统计</h2>");
html.AppendLine("<table>");
html.AppendLine(" <tr>");

View File

@@ -25,6 +25,16 @@ namespace LogParse
public List<ActionItem> SmallMonsterActionItems =>
this.MonsterActionItems.Except(EliteMonsterActionItems).ToList();
public string EmergencyBonus
{
get
{
var ls = this.ActionItems.Where(item => item.ActionId == 28).ToList();
var count = ls.Count();
return ls.Sum(item=>item.Num)+((count==0 || count>=10)?"":$"({count}/10)");
}
}
public string LastEliteTime => EliteMonsterActionItems.MaxBy(item => item?.Time)?.Time ?? null;
public string LastSmallTime => SmallMonsterActionItems.MaxBy(item => item?.Time)?.Time ?? null;

View File

@@ -50,8 +50,8 @@ public class TravelsDiaryDetailManager
var _temp = JsonSerializer.Deserialize<ApiResponse<ActionItem>>(File.ReadAllText(tddfile));
if (_temp != null)
{
//统计杀怪
actionItems.AddRange(_temp.Data.List.Where(item => item.ActionId == 37));
//统计杀怪或突发事件奖励
actionItems.AddRange(_temp.Data.List.Where(item => item.ActionId == 37 || item.ActionId == 28));
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -34,6 +34,7 @@ public class QuickTeleportAssets : BaseAssets<QuickTeleportAssets>
BuildMapChooseIconRo("StatueOfTheSeven.png"),
BuildMapChooseIconRo("Domain.png"),
BuildMapChooseIconRo("Domain2.png"),
BuildMapChooseIconRo("ObsidianTotemPole.png"),
BuildMapChooseIconRo("PortableWaypoint.png"),
BuildMapChooseIconRo("Mansion.png"),
BuildMapChooseIconRo("SubSpaceWaypoint.png"),
@@ -140,7 +141,6 @@ public class QuickTeleportAssets : BaseAssets<QuickTeleportAssets>
/// <returns></returns>
public RecognitionObject BuildMapChooseIconRo(string name)
{
var info = TaskContext.Instance().SystemInfo;
var ro = new RecognitionObject
{
Name = name + "MapChooseIcon",

View File

@@ -65,7 +65,7 @@ namespace BetterGenshinImpact.GameTask
}
}
public SettingsContainer? GameSettings { get; set; }
// public SettingsContainer? GameSettings { get; set; }
/// <summary>
/// 关联启动原神的时间

View File

@@ -10,7 +10,7 @@ using System.Threading.Tasks;
using BetterGenshinImpact.Helpers;
using Wpf.Ui.Violeta.Controls;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
using BetterGenshinImpact.Core.Recorder;
using BetterGenshinImpact.Service;
namespace BetterGenshinImpact.GameTask;
@@ -119,6 +119,8 @@ public class TaskRunner
public async Task RunSoloTaskAsync(ISoloTask soloTask)
{
// 没启动的时候先启动
await ScriptService.StartGameTask();
await Task.Run(() => RunCurrentAsync(async () => await soloTask.Start(CancellationContext.Instance.Cts.Token)));
}

View File

@@ -33,6 +33,15 @@ public class DirectoryHelper
private static void DeleteDirectory(DirectoryInfo directoryInfo)
{
//通过软链接生成的目录,直接删除该链接目录,而不涉及其文件本体
var attributes = directoryInfo.Attributes;
if ((attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
{
directoryInfo.Delete();
return;
}
// 递归处理子目录
foreach (var subDirectory in directoryInfo.GetDirectories())
{
@@ -80,4 +89,54 @@ public class DirectoryHelper
RemoveReadOnlyAttribute(subDirectory);
}
}
public static void CopyDirectory(string sourceDir, string destDir)
{
// 创建目标目录
Directory.CreateDirectory(destDir);
// 获取源目录中的所有文件
foreach (var file in Directory.GetFiles(sourceDir))
{
var destFile = Path.Combine(destDir, Path.GetFileName(file));
File.Copy(file, destFile, true); // 覆盖同名文件
}
// 获取源目录中的所有子目录
foreach (var subDir in Directory.GetDirectories(sourceDir))
{
var destSubDir = Path.Combine(destDir, Path.GetFileName(subDir));
CopyDirectory(subDir, destSubDir); // 递归拷贝子目录
}
}
/// <summary>
/// 递归删除指定目录及其所有子目录和文件
/// </summary>
/// <param name="directoryPath">要删除的目录的路径</param>
public static void DeleteDirectoryRecursively(string directoryPath)
{
// 检查目录是否存在
if (Directory.Exists(directoryPath))
{
// 获取目录中的所有子目录
string[] subDirectories = Directory.GetDirectories(directoryPath);
foreach (string subDirectory in subDirectories)
{
// 递归调用删除子目录
DeleteDirectoryRecursively(subDirectory);
}
// 获取目录中的所有文件
string[] files = Directory.GetFiles(directoryPath);
foreach (string file in files)
{
// 删除文件
File.Delete(file);
}
// 删除空目录
Directory.Delete(directoryPath);
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Windows.Media;
using System.Diagnostics;
using System.Windows.Media;
using BetterGenshinImpact.GameTask;
using Wpf.Ui.Controls;
@@ -8,14 +9,16 @@ public class WindowHelper
{
public static void TryApplySystemBackdrop(System.Windows.Window window)
{
window.Background = new SolidColorBrush(Colors.Transparent);
if (WindowBackdrop.IsSupported(TaskContext.Instance().Config.CommonConfig.CurrentBackdropType))
{
if (TaskContext.Instance().Config.CommonConfig.CurrentBackdropType == WindowBackdropType.Acrylic)
{
window.Background = new SolidColorBrush(Color.FromArgb(100, 0, 0, 0));
}
else
{
window.Background = new SolidColorBrush(Colors.Transparent);
}
WindowBackdrop.ApplyBackdrop(window, TaskContext.Instance().Config.CommonConfig.CurrentBackdropType);
return;
@@ -24,14 +27,12 @@ public class WindowHelper
if (WindowBackdrop.IsSupported(WindowBackdropType.Mica))
{
window.Background = new SolidColorBrush(Colors.Transparent);
WindowBackdrop.ApplyBackdrop(window, WindowBackdropType.Mica);
}
else if (WindowBackdrop.IsSupported(WindowBackdropType.Tabbed))
{
WindowBackdrop.ApplyBackdrop(window, WindowBackdropType.Tabbed);
}
else if (WindowBackdrop.IsSupported(WindowBackdropType.Acrylic))
{
window.Background = new SolidColorBrush(Color.FromArgb(100, 0, 0, 0));
WindowBackdrop.ApplyBackdrop(window, WindowBackdropType.Acrylic);
}
}

View File

@@ -93,14 +93,14 @@ public class UpdateService : IUpdateService
case CheckUpdateWindow.CheckUpdateWindowButton.Update:
{
// 唤起更新程序
string updaterExePath = Global.Absolute("updater.exe");
string updaterExePath = Global.Absolute("BetterGI.update.exe");
if (!File.Exists(updaterExePath))
{
await MessageBox.ErrorAsync("更新程序不存在,请选择其他更新方式!");
return;
}
// 启动
Process.Start(updaterExePath);
Process.Start(updaterExePath, "-I");
// 退出程序
Application.Current.Shutdown();

View File

@@ -176,26 +176,26 @@ public partial class MaskWindow : Window
}
// 读取游戏注册表配置
ReadGameSettings();
// ReadGameSettings();
}
private void ReadGameSettings()
{
try
{
SettingsContainer settings = new();
TaskContext.Instance().GameSettings = settings;
var lang = settings.Language?.TextLang;
if (lang != null && lang != TextLanguage.SimplifiedChinese)
{
_logger.LogWarning("当前游戏语言{Lang}不是简体中文部分功能可能无法正常使用。The game language is not Simplified Chinese, some functions may not work properly", lang);
}
}
catch (Exception e)
{
_logger.LogWarning("游戏注册表配置信息读取失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
}
}
// private void ReadGameSettings()
// {
// try
// {
// SettingsContainer settings = new();
// TaskContext.Instance().GameSettings = settings;
// var lang = settings.Language?.TextLang;
// if (lang != null && lang != TextLanguage.SimplifiedChinese)
// {
// _logger.LogWarning("当前游戏语言{Lang}不是简体中文部分功能可能无法正常使用。The game language is not Simplified Chinese, some functions may not work properly", lang);
// }
// }
// catch (Exception e)
// {
// _logger.LogWarning("游戏注册表配置信息读取失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
// }
// }
protected override void OnSourceInitialized(EventArgs e)
{

View File

@@ -428,7 +428,34 @@
</b:Interaction.Triggers>
</ComboBox>
</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="根据技能CD优化出招人员"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="0"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="根据填入人或人和cd来决定当此人元素战技cd未结束时跳过此人出招来优化战斗流程可填入人名或人名数字用逗号分隔多种用分号分隔例如:白术;钟离,12;如果人名则用内置cd检查或填入数字也小于0如果是人名和数字则把数字当做出招cd(秒)。"
TextWrapping="Wrap" />
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
MinWidth="180"
MaxWidth="800"
Margin="0,0,36,0"
Text="{Binding Config.AutoFightConfig.ActionSchedulerByCd, Mode=TwoWay}"
TextWrapping="Wrap" />
</Grid>
<!--内嵌的设置-->
<Separator Margin="-18,0" BorderThickness="0,1,0,0" />
<Grid Margin="16,10,52,0">
@@ -624,33 +651,147 @@
</ui:CardExpander>
</Grid>
<Separator Margin="-18,0" BorderThickness="0,1,0,0" />
<Grid Margin="16,10,52,0">
<ui:CardExpander Margin="0,0,0,12"
ContentPadding="0"
IsExpanded="False">
<ui:CardExpander.Header>
<Grid>
<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:ToggleSwitch Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
Margin="0,0,36,0"
IsChecked="{Binding Config.AutoFightConfig.PickDropsAfterFightEnabled}"/>
</Grid>
</ui:CardExpander.Header>
<StackPanel>
<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"
Text="{Binding Config.AutoFightConfig.PickDropsConfig.ForwardTimes}"/>
</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"
Text="{Binding Config.AutoFightConfig.PickDropsConfig.CalibrationTimes}"/>
</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="视角调整的精细程度应在0.5到1之间数值越小越精细数值越高校准范围越大"
TextWrapping="Wrap"/>
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
MinWidth="120"
Text="{Binding Config.AutoFightConfig.PickDropsConfig.DecayFactor}"/>
</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="每次视角校准后前进的时长。设置为0时前进量在1到3秒内随机大了可能跑到奇奇怪怪的地方去小了可能采集不到可以和前进次数配合"
TextWrapping="Wrap"/>
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
MinWidth="120"
Text="{Binding Config.AutoFightConfig.PickDropsConfig.ForwardSeconds}"/>
</Grid>
</StackPanel>
</ui:CardExpander>
<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:ToggleSwitch Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
Margin="0,0,36,0"
IsChecked="{Binding Config.AutoFightConfig.PickDropsAfterFightEnabled, Mode=TwoWay}" />
</Grid>
<Separator Margin="-18,0" BorderThickness="0,1,0,0" />
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />

View File

@@ -778,7 +778,166 @@
</Grid>
</StackPanel>
</ui:CardExpander>
<!-- 快速传送 -->
<ui:CardExpander Margin="0,0,0,12" ContentPadding="0">
<ui:CardExpander.Icon>
<ui:FontIcon Glyph="&#xf3c5;" Style="{StaticResource FaFontIconStyle}" />
</ui:CardExpander.Icon>
<ui:CardExpander.Header>
<Grid>
<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" />
</Grid>
</ui:CardExpander.Header>
<StackPanel>
<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:ToggleSwitch Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
Margin="0,0,36,0"
IsChecked="{Binding Config.TpConfig.MapZoomEnabled, Mode=TwoWay}" />
</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="90"
Margin="0,0,36,0"
Text="{Binding Config.TpConfig.MaxMouseMove, Mode=TwoWay}" />
</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="90"
Margin="0,0,36,0"
Text="{Binding Config.TpConfig.MapZoomOutDistance, Mode=TwoWay}" />
</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="90"
Margin="0,0,36,0"
Text="{Binding Config.TpConfig.MapZoomInDistance, Mode=TwoWay}" />
</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="90"
Margin="0,0,36,0"
Text="{Binding Config.TpConfig.StepIntervalMilliseconds, Mode=TwoWay}" />
</Grid>
</StackPanel>
</ui:CardExpander>
<!-- 自动烹饪 -->
<ui:CardControl Margin="0,0,0,12">
<ui:CardControl.Icon>

View File

@@ -370,6 +370,34 @@
</b:Interaction.Triggers>
</ComboBox>
</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="根据技能CD优化出招人员"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="0"
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
Text="根据填入人或人和cd来决定当此人元素战技cd未结束时跳过此人出招来优化战斗流程可填入人名或人名数字用逗号分隔多种用分号分隔例如:白术;钟离,12;如果人名则用内置cd检查或填入数字也小于0如果是人名和数字则把数字当做出招cd(秒)。"
TextWrapping="Wrap" />
<ui:TextBox Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
MinWidth="180"
MaxWidth="800"
Margin="0,0,36,0"
Text="{Binding PathingConfig.AutoFightConfig.ActionSchedulerByCd, Mode=TwoWay}"
TextWrapping="Wrap" />
</Grid>
<Grid Margin="16">
<ui:CardExpander Margin="0,0,0,12"

View File

@@ -15,11 +15,13 @@ using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using BetterGenshinImpact.ViewModel.Pages;
using Wpf.Ui;
using Wpf.Ui.Controls;
@@ -39,7 +41,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
[ObservableProperty]
public WindowBackdropType _currentBackdropType = WindowBackdropType.Auto;
public AllConfig Config { get; set; }
public MainWindowViewModel(INavigationService navigationService, IConfigService configService)
@@ -60,23 +62,27 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
{
IsVisible = false;
}
[RelayCommand]
private void OnSwitchBackdrop()
{
if (!OsVersionHelper.IsWindows11_22523_OrGreater)
{
return; // win10 不支持切换主题
}
CurrentBackdropType = CurrentBackdropType switch
{
WindowBackdropType.Auto => WindowBackdropType.Mica,
WindowBackdropType.Mica => WindowBackdropType.Acrylic,
WindowBackdropType.Acrylic => WindowBackdropType.Tabbed,
WindowBackdropType.Tabbed => WindowBackdropType.Auto,
_ => WindowBackdropType.Auto
WindowBackdropType.Acrylic => WindowBackdropType.Mica,
_ => WindowBackdropType.Acrylic
};
Config.CommonConfig.CurrentBackdropType = CurrentBackdropType;
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.Background = new SolidColorBrush(Color.FromArgb(100, 0, 0, 0));;
mainWindow.Background = new SolidColorBrush(Color.FromArgb(100, 0, 0, 0));
WindowBackdrop.ApplyBackdrop(mainWindow, CurrentBackdropType);
}
}
@@ -92,8 +98,78 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
}
[RelayCommand]
[SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", "MVVMTK0039:Async void returning method annotated with RelayCommand")]
private async void OnLoaded()
private async Task OnLoaded()
{
// 自动处理目录配置
await Patch1();
// 预热OCR
await OcrPreheating();
// 首次运行自动初始化绑定
InitKeyBinding();
// 检查更新
await App.GetService<IUpdateService>()!.CheckUpdateAsync(new UpdateOption());
// Win11下 BitBlt截图方式不可用需要关闭窗口优化功能
if (OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt)
{
BitBltRegistryHelper.SetDirectXUserGlobalSettings();
}
// 更新仓库
ScriptRepoUpdater.Instance.AutoUpdate();
}
private void InitKeyBinding()
{
if (Config.CommonConfig.IsFirstRun)
{
try
{
var kbVm = App.GetService<KeyBindingsSettingsPageViewModel>();
if (kbVm != null)
{
kbVm.FetchFromRegistryCommand.Execute(null);
}
}
catch (Exception e)
{
_logger.LogError("首次运行自动初始化按键绑定异常:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
MessageBox.Error("读取原神键位并设置键位绑定数据时发生异常:" + e.Message + ",后续可以手动设置");
}
}
}
/**
* 不同的安装目录处理
* 可能当前目录下存在 BetterGI 的文件,需要移动到新的目录
*/
private async Task Patch1()
{
if (Directory.Exists(Global.Absolute("BetterGI"))
// && File.Exists(Global.Absolute("BetterGI/BetterGI.exe"))
&& Directory.Exists(Global.Absolute("BetterGI/User"))
)
{
var res = await MessageBox.ShowAsync("检测到旧的 BetterGI 配置,是否迁移配置并清理旧目录?", "BetterGI", System.Windows.MessageBoxButton.YesNo, MessageBoxImage.Question);
if (res == System.Windows.MessageBoxResult.Yes)
{
var dir = Global.Absolute("BetterGI/User");
// 迁移配置,拷贝整个目录并覆盖
DirectoryHelper.CopyDirectory(dir, Global.Absolute("User"));
// 删除旧目录
DirectoryHelper.DeleteDirectoryRecursively(Global.Absolute("BetterGI"));
}
}
}
private async Task OcrPreheating()
{
try
{
@@ -125,16 +201,5 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
{
MessageBox.Warning("PaddleOcr预热失败解决方案https://bgi.huiyadan.com/faq.html" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
}
await App.GetService<IUpdateService>()!.CheckUpdateAsync(new UpdateOption());
// Win11下 BitBlt截图方式不可用需要关闭窗口优化功能
if (OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt)
{
BitBltRegistryHelper.SetDirectXUserGlobalSettings();
}
// 更新仓库
ScriptRepoUpdater.Instance.AutoUpdate();
}
}
}

View File

@@ -372,7 +372,7 @@ public partial class KeyBindingsSettingsPageViewModel : ObservableObject, INavig
{
foreach (var item in keySetting)
{
if (item.ElementIdentifierId is ElementIdentifierId keyId)
if (item.ElementIdentifierId is { } keyId)
{
// 跳过无法识别的按键
if (keyId.ToName() == "Unknown" || keyId.ToName() == "None")

View File

@@ -702,6 +702,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware
private List<ScriptProject> LoadAllJsScriptProjects()
{
var path = Global.ScriptPath();
Directory.CreateDirectory(path);
// 获取所有脚本项目
var projects = Directory.GetDirectories(path)
.Select(x => new ScriptProject(Path.GetFileName(x)))