diff --git a/.gitignore b/.gitignore index 5de9c4d3..db7561af 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,6 @@ node_modules/ # Rider .idea -.trae \ No newline at end of file +.trae +.claude +CLAUDE.md \ No newline at end of file diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index c8c2f519..808b0cc0 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -163,6 +163,8 @@ Always + + Always Always diff --git a/BetterGenshinImpact/Core/Config/AllConfig.cs b/BetterGenshinImpact/Core/Config/AllConfig.cs index d1624e3b..742043f2 100644 --- a/BetterGenshinImpact/Core/Config/AllConfig.cs +++ b/BetterGenshinImpact/Core/Config/AllConfig.cs @@ -21,6 +21,7 @@ using BetterGenshinImpact.GameTask.AutoTrackPath; using BetterGenshinImpact.GameTask.AutoArtifactSalvage; using BetterGenshinImpact.GameTask.AutoStygianOnslaught; using BetterGenshinImpact.GameTask.GetGridIcons; +using BetterGenshinImpact.GameTask.AutoEat; namespace BetterGenshinImpact.Core.Config; @@ -165,6 +166,11 @@ public partial class AllConfig : ObservableObject /// public AutoArtifactSalvageConfig AutoArtifactSalvageConfig { get; set; } = new(); + /// + /// 自动吃药配置 + /// + public AutoEatConfig AutoEatConfig { get; set; } = new(); + /// /// 截取物品图标配置 /// @@ -247,6 +253,7 @@ public partial class AllConfig : ObservableObject AutoDomainConfig.PropertyChanged += OnAnyPropertyChanged; AutoStygianOnslaughtConfig.PropertyChanged += OnAnyPropertyChanged; AutoArtifactSalvageConfig.PropertyChanged += OnAnyPropertyChanged; + AutoEatConfig.PropertyChanged += OnAnyPropertyChanged; AutoMusicGameConfig.PropertyChanged += OnAnyPropertyChanged; TpConfig.PropertyChanged += OnAnyPropertyChanged; ScriptConfig.PropertyChanged += OnAnyPropertyChanged; diff --git a/BetterGenshinImpact/Core/Config/PathingConditionConfig.cs b/BetterGenshinImpact/Core/Config/PathingConditionConfig.cs index cee56ae1..47a5d6ea 100644 --- a/BetterGenshinImpact/Core/Config/PathingConditionConfig.cs +++ b/BetterGenshinImpact/Core/Config/PathingConditionConfig.cs @@ -29,6 +29,10 @@ public partial class PathingConditionConfig : ObservableObject // 使用小道具的间隔时间(ms) [ObservableProperty] private int _useGadgetIntervalMs = 0; + + // 启用自动吃药功能 + [ObservableProperty] + private bool _autoEatEnabled = true; public static PathingConditionConfig Default => new() { diff --git a/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs b/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs index 72f55a27..432ce486 100644 --- a/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs +++ b/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs @@ -92,6 +92,10 @@ public partial class PathingPartyConfig : ObservableObject [ObservableProperty] private bool _autoRunEnabled = true; + // 启用自动吃药功能 + [ObservableProperty] + private bool _autoEatEnabled = true; + //在连续执行时是否隐藏 [ObservableProperty] private bool _hideOnRepeat = false; @@ -120,7 +124,8 @@ public partial class PathingPartyConfig : ObservableObject return new PathingPartyConfig { OnlyInTeleportRecover = pathingConditionConfig.OnlyInTeleportRecover, - UseGadgetIntervalMs = pathingConditionConfig.UseGadgetIntervalMs + UseGadgetIntervalMs = pathingConditionConfig.UseGadgetIntervalMs, + AutoEatEnabled = pathingConditionConfig.AutoEatEnabled }; } } diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs index 0fc98ffb..9d0deeac 100644 --- a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs @@ -667,11 +667,11 @@ public class AutoDomainTask : ISoloTask // 对局结束检测 var domainEndTask = DomainEndDetectionTask(cts); // 自动吃药 - var autoEatRecoveryHpTask = AutoEatRecoveryHpTask(cts.Token); + // var autoEatRecoveryHpTask = AutoEatRecoveryHpTask(cts.Token); combatTask.Start(); domainEndTask.Start(); - autoEatRecoveryHpTask.Start(); - return Task.WhenAll(combatTask, domainEndTask, autoEatRecoveryHpTask); + // autoEatRecoveryHpTask.Start(); + return Task.WhenAll(combatTask, domainEndTask); } private void EndFightWait() diff --git a/BetterGenshinImpact/GameTask/AutoEat/Assets/1920x1080/Recovery.png b/BetterGenshinImpact/GameTask/AutoEat/Assets/1920x1080/Recovery.png new file mode 100644 index 00000000..a1b0c82c Binary files /dev/null and b/BetterGenshinImpact/GameTask/AutoEat/Assets/1920x1080/Recovery.png differ diff --git a/BetterGenshinImpact/GameTask/AutoEat/Assets/1920x1080/Resurrection.png b/BetterGenshinImpact/GameTask/AutoEat/Assets/1920x1080/Resurrection.png new file mode 100644 index 00000000..d50b9546 Binary files /dev/null and b/BetterGenshinImpact/GameTask/AutoEat/Assets/1920x1080/Resurrection.png differ diff --git a/BetterGenshinImpact/GameTask/AutoEat/Assets/AutoEatAssets.cs b/BetterGenshinImpact/GameTask/AutoEat/Assets/AutoEatAssets.cs new file mode 100644 index 00000000..bc55e1d7 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoEat/Assets/AutoEatAssets.cs @@ -0,0 +1,37 @@ +using BetterGenshinImpact.Core.Recognition; +using BetterGenshinImpact.Core.Recognition.OpenCv; +using BetterGenshinImpact.GameTask.Model; +using OpenCvSharp; + +namespace BetterGenshinImpact.GameTask.AutoEat.Assets; + +public class AutoEatAssets : BaseAssets +{ + public RecognitionObject RecoveryIconRa; + public RecognitionObject ResurrectionIconRa; + + private AutoEatAssets() + { + var s = TaskContext.Instance().SystemInfo.AssetScale; + + RecoveryIconRa = new RecognitionObject + { + Name = "RecoveryIcon", + RecognitionType = RecognitionTypes.TemplateMatch, + TemplateImageMat = GameTaskManager.LoadAssetImage("AutoEat", "Recovery.png"), + Threshold = 0.8, + RegionOfInterest = new Rect((int)(1810 * s), (int)(778 * s), (int)(23 * s), (int)(23 * s)), + DrawOnWindow = false + }.InitTemplate(); + + ResurrectionIconRa = new RecognitionObject + { + Name = "ResurrectionIcon", + RecognitionType = RecognitionTypes.TemplateMatch, + TemplateImageMat = GameTaskManager.LoadAssetImage("AutoEat", "Resurrection.png"), + Threshold = 0.8, + RegionOfInterest = new Rect((int)(1810 * s), (int)(778 * s), (int)(18 * s), (int)(19 * s)), + DrawOnWindow = false + }.InitTemplate(); + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoEat/AutoEatConfig.cs b/BetterGenshinImpact/GameTask/AutoEat/AutoEatConfig.cs new file mode 100644 index 00000000..3f11bcb2 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoEat/AutoEatConfig.cs @@ -0,0 +1,36 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; + +namespace BetterGenshinImpact.GameTask.AutoEat; + +/// +/// 自动吃药配置 +/// +[Serializable] +public partial class AutoEatConfig : ObservableObject +{ + /// + /// 是否启用自动吃药 + /// + [ObservableProperty] + private bool _enabled = true; + + /// + /// 是否显示吃药通知 + /// + [ObservableProperty] + private bool _showNotification = true; + + /// + /// 检测间隔时间(毫秒) + /// + [ObservableProperty] + private int _checkInterval = 500; + + /// + /// 吃药间隔时间(毫秒) + /// 防止频繁吃药 + /// + [ObservableProperty] + private int _eatInterval = 2000; +} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoEat/AutoEatParam.cs b/BetterGenshinImpact/GameTask/AutoEat/AutoEatParam.cs new file mode 100644 index 00000000..1777886d --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoEat/AutoEatParam.cs @@ -0,0 +1,37 @@ +using BetterGenshinImpact.GameTask.Model; + +namespace BetterGenshinImpact.GameTask.AutoEat; + +/// +/// 自动吃药任务参数 +/// +public class AutoEatParam : BaseTaskParam +{ + /// + /// 是否显示通知 + /// + public bool ShowNotification { get; set; } + + /// + /// 检测间隔(毫秒) + /// + public int CheckInterval { get; set; } + + /// + /// 吃药间隔(毫秒) + /// + public int EatInterval { get; set; } + + public AutoEatParam() + { + SetDefault(); + } + + public void SetDefault() + { + var config = TaskContext.Instance().Config.AutoEatConfig; + ShowNotification = config.ShowNotification; + CheckInterval = config.CheckInterval; + EatInterval = config.EatInterval; + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoEat/AutoEatTask.cs b/BetterGenshinImpact/GameTask/AutoEat/AutoEatTask.cs new file mode 100644 index 00000000..90b151ba --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoEat/AutoEatTask.cs @@ -0,0 +1,131 @@ +using BetterGenshinImpact.Core.Recognition.OCR; +using BetterGenshinImpact.Core.Simulator; +using BetterGenshinImpact.Core.Simulator.Extensions; +using BetterGenshinImpact.GameTask.Common.BgiVision; +using BetterGenshinImpact.GameTask.Common.Element.Assets; +using BetterGenshinImpact.GameTask.Model; +using BetterGenshinImpact.Service.Notification; +using BetterGenshinImpact.Service.Notification.Model.Enum; +using Microsoft.Extensions.Logging; +using System; +using System.Threading; +using System.Threading.Tasks; +using static BetterGenshinImpact.GameTask.Common.TaskControl; + +namespace BetterGenshinImpact.GameTask.AutoEat; + +/// +/// 自动吃药任务 +/// 检测红血自动使用便携营养袋 +/// +public class AutoEatTask : BaseIndependentTask, ISoloTask +{ + public string Name => "自动吃药"; + + private readonly AutoEatParam _taskParam; + private readonly AutoEatConfig _config; + private CancellationToken _ct; + + public AutoEatTask(AutoEatParam taskParam) + { + _taskParam = taskParam; + _config = TaskContext.Instance().Config.AutoEatConfig; + } + + public async Task Start(CancellationToken ct) + { + _ct = ct; + + Init(); + Logger.LogInformation("自动吃药任务启动"); + + if (!IsTakeFood()) + { + Logger.LogWarning("未装备 \"{Tool}\",无法启用自动吃药功能", "便携营养袋"); + return; + } + + try + { + await AutoEatLoop(); + } + catch (Exception e) + { + Logger.LogError(e, "自动吃药任务发生异常"); + throw; + } + finally + { + Logger.LogInformation("自动吃药任务结束"); + } + } + + private void Init() + { + Logger.LogInformation("→ {Text} 检测间隔: {Interval}ms", "自动吃药,", _config.CheckInterval); + Logger.LogInformation("→ {Text} 吃药间隔: {Interval}ms", "自动吃药,", _config.EatInterval); + } + + /// + /// 自动吃药主循环 + /// + private async Task AutoEatLoop() + { + var lastEatTime = DateTime.MinValue; + + while (!_ct.IsCancellationRequested) + { + try + { + // 检测当前角色是否红血 + if (Bv.CurrentAvatarIsLowHp(CaptureToRectArea())) + { + var now = DateTime.Now; + // 检查是否超过吃药间隔时间,避免重复吃药 + if ((now - lastEatTime).TotalMilliseconds >= _config.EatInterval) + { + // 模拟按键 "Z" 使用便携营养袋 + Simulation.SendInput.SimulateAction(GIActions.QuickUseGadget); + lastEatTime = now; + + Logger.LogInformation("检测到红血,自动吃药"); + } + } + + await Delay(_config.CheckInterval, _ct); + } + catch (OperationCanceledException) + { + // 任务被取消,正常退出 + break; + } + catch (Exception e) + { + Logger.LogDebug(e, "自动吃药检测时发生异常"); + await Delay(1000, _ct); // 异常时稍作等待 + } + } + } + + /// + /// 检测是否装备了便携营养袋 + /// + private bool IsTakeFood() + { + try + { + // 获取图像 + using var ra = CaptureToRectArea(); + // 识别道具图标下是否是数字 + var s = TaskContext.Instance().SystemInfo.AssetScale; + var countArea = ra.DeriveCrop(1800 * s, 845 * s, 40 * s, 20 * s); + var count = OcrFactory.Paddle.OcrWithoutDetector(countArea.CacheGreyMat); + return int.TryParse(count, out _); + } + catch (Exception e) + { + Logger.LogDebug(e, "检测便携营养袋时发生异常"); + return false; + } + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoEat/AutoEatTrigger.cs b/BetterGenshinImpact/GameTask/AutoEat/AutoEatTrigger.cs new file mode 100644 index 00000000..9d1ed670 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoEat/AutoEatTrigger.cs @@ -0,0 +1,139 @@ +using BetterGenshinImpact.Core.Simulator; +using BetterGenshinImpact.Core.Simulator.Extensions; +using BetterGenshinImpact.GameTask.Common; +using BetterGenshinImpact.GameTask.Common.BgiVision; +using BetterGenshinImpact.GameTask.Model.Area; +using BetterGenshinImpact.GameTask.AutoEat.Assets; +using BetterGenshinImpact.Service.Notification; +using BetterGenshinImpact.Service.Notification.Model.Enum; +using Microsoft.Extensions.Logging; +using System; +using static BetterGenshinImpact.GameTask.Common.TaskControl; +using static Vanara.PInvoke.User32; + +namespace BetterGenshinImpact.GameTask.AutoEat; + +/// +/// 自动吃药触发器 +/// 检测红血状态时自动使用Recovery.png,检测到Resurrection.png时按z复活 +/// +public class AutoEatTrigger : ITaskTrigger +{ + private readonly ILogger _logger = App.GetLogger(); + + public string Name => "自动吃药"; + public bool IsEnabled { get; set; } + public int Priority => 25; // 中等优先级 + public bool IsExclusive => false; + + private readonly AutoEatConfig _config; + private DateTime _lastRecoveryCheckTime = DateTime.MinValue; + private DateTime _lastResurrectionTime = DateTime.MinValue; + private DateTime _lastEatTime = DateTime.MinValue; + private bool _recoveryDetected = false; + + public AutoEatTrigger() + { + _config = TaskContext.Instance().Config.AutoEatConfig; + } + + public void Init() + { + IsEnabled = _config.Enabled; + } + + public void OnCapture(CaptureContent content) + { + if (!IsEnabled) + return; + + try + { + using var ra = TaskControl.CaptureToRectArea(); + var now = DateTime.Now; + + // 优先检测复活图标,添加2秒CD + if (CheckResurrection(ra)) + { + // 检查复活CD(2秒) + if ((now - _lastResurrectionTime).TotalSeconds >= 2) + { + // 按z键复活 + Simulation.SendInput.Keyboard.KeyPress(VK.VK_Z); + _lastResurrectionTime = now; + _logger.LogInformation("检测到复活图标,自动复活"); + } + return; + } + + // 检测角色是否红血 + if (Bv.CurrentAvatarIsLowHp(ra)) + { + // 检查Recovery缓存是否过期(30秒) + if ((now - _lastRecoveryCheckTime).TotalSeconds >= 30) + { + _recoveryDetected = false; + _lastRecoveryCheckTime = now; + } + + // 如果Recovery还在缓存期内,或者重新检测到Recovery + if (_recoveryDetected || CheckRecovery(ra)) + { + if (!_recoveryDetected) + { + _recoveryDetected = true; + _lastRecoveryCheckTime = now; + } + + // 检查吃药间隔,防止频繁吃药 + if ((now - _lastEatTime).TotalMilliseconds >= _config.EatInterval) + { + // 使用便携营养袋 + Simulation.SendInput.SimulateAction(GIActions.QuickUseGadget); + _lastEatTime = now; + + _logger.LogInformation("检测到红血且Recovery可用,自动吃药"); + } + } + } + } + catch (Exception e) + { + _logger.LogDebug(e, "自动吃药检测时发生异常"); + } + } + + /// + /// 检测Recovery.png图标 + /// + private bool CheckRecovery(ImageRegion imageRegion) + { + try + { + var result = imageRegion.Find(AutoEatAssets.Instance.RecoveryIconRa); + return result.IsExist(); + } + catch (Exception e) + { + _logger.LogDebug(e, "检测Recovery图标时发生异常"); + return false; + } + } + + /// + /// 检测Resurrection.png图标 + /// + private bool CheckResurrection(ImageRegion imageRegion) + { + try + { + var result = imageRegion.Find(AutoEatAssets.Instance.ResurrectionIconRa); + return result.IsExist(); + } + catch (Exception e) + { + _logger.LogDebug(e, "检测Resurrection图标时发生异常"); + return false; + } + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/GameTaskManager.cs b/BetterGenshinImpact/GameTask/GameTaskManager.cs index ccf8b735..c7a583f3 100644 --- a/BetterGenshinImpact/GameTask/GameTaskManager.cs +++ b/BetterGenshinImpact/GameTask/GameTaskManager.cs @@ -7,6 +7,7 @@ using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Assets; using BetterGenshinImpact.GameTask.AutoPick.Assets; using BetterGenshinImpact.GameTask.AutoSkip.Assets; using BetterGenshinImpact.GameTask.AutoWood.Assets; +using BetterGenshinImpact.GameTask.AutoEat.Assets; using BetterGenshinImpact.GameTask.Common.Element.Assets; using BetterGenshinImpact.GameTask.GameLoading; using BetterGenshinImpact.GameTask.GameLoading.Assets; @@ -45,6 +46,7 @@ internal class GameTaskManager TriggerDictionary.TryAdd("AutoSkip", new AutoSkip.AutoSkipTrigger()); TriggerDictionary.TryAdd("AutoFish", new AutoFishing.AutoFishingTrigger()); TriggerDictionary.TryAdd("AutoCook", new AutoCook.AutoCookTrigger()); + TriggerDictionary.TryAdd("AutoEat", new AutoEat.AutoEatTrigger()); return ConvertToTriggerList(); } @@ -94,6 +96,10 @@ internal class GameTaskManager triggerName = "AutoSkip"; trigger = new AutoSkip.AutoSkipTrigger(); break; + case "AutoEat": + triggerName = "AutoEat"; + trigger = new AutoEat.AutoEatTrigger(); + break; } if (triggerName == null || trigger == null) @@ -114,6 +120,7 @@ internal class GameTaskManager TriggerDictionary.GetValueOrDefault("QuickTeleport")?.Init(); // TriggerDictionary.GetValueOrDefault("GameLoading")?.Init(); TriggerDictionary.GetValueOrDefault("AutoCook")?.Init(); + TriggerDictionary.GetValueOrDefault("AutoEat")?.Init(); // 清理画布 VisionContext.Instance().DrawContent.ClearAll(); } @@ -134,6 +141,7 @@ internal class GameTaskManager QuickSereniteaPotAssets.DestroyInstance(); GameLoadingAssets.DestroyInstance(); MapLazyAssets.DestroyInstance(); + AutoEatAssets.DestroyInstance(); } /// diff --git a/BetterGenshinImpact/GameTask/TaskRunner.cs b/BetterGenshinImpact/GameTask/TaskRunner.cs index b2c4c532..4dbc0489 100644 --- a/BetterGenshinImpact/GameTask/TaskRunner.cs +++ b/BetterGenshinImpact/GameTask/TaskRunner.cs @@ -133,6 +133,9 @@ public class TaskRunner // 清空实时任务触发器 TaskTriggerDispatcher.Instance().ClearTriggers(); + // 重新加载基础触发器(包括自动吃药等实时功能) + var basicTriggers = GameTaskManager.LoadInitialTriggers(); + TaskTriggerDispatcher.Instance().SetTriggers(basicTriggers); // 激活原神窗口 var maskWindow = MaskWindow.Instance(); diff --git a/BetterGenshinImpact/Service/Notification/Model/Enum/NotificationEvent.cs b/BetterGenshinImpact/Service/Notification/Model/Enum/NotificationEvent.cs index 79c3b3fc..ec1a82de 100644 --- a/BetterGenshinImpact/Service/Notification/Model/Enum/NotificationEvent.cs +++ b/BetterGenshinImpact/Service/Notification/Model/Enum/NotificationEvent.cs @@ -21,6 +21,9 @@ public class NotificationEvent(string code, string msg) public static readonly NotificationEvent DailyReward = new("daily.reward", "检查每日奖励领取状态"); public static readonly NotificationEvent JsCustom = new("js.custom", "JS自定义事件"); public static readonly NotificationEvent JsError = new("js.error", "JS运行时错误"); + public static readonly NotificationEvent AutoEatStart = new("autoeat.start", "自动吃药启动"); + public static readonly NotificationEvent AutoEatEnd = new("autoeat.end", "自动吃药结束"); + public static readonly NotificationEvent AutoEatInfo = new("autoeat.info", "自动吃药信息"); public string Code { get; private set; } = code; public string Msg { get; private set; } = msg; diff --git a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml index a0fdf3b0..9ef5895b 100644 --- a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml @@ -1001,6 +1001,7 @@ + diff --git a/BetterGenshinImpact/View/Pages/TriggerSettingsPage.xaml b/BetterGenshinImpact/View/Pages/TriggerSettingsPage.xaml index d422a037..a6565ea9 100644 --- a/BetterGenshinImpact/View/Pages/TriggerSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/TriggerSettingsPage.xaml @@ -643,6 +643,68 @@ + + + + + + + + + + + + + + + + + + 检测角色红血状态,自动使用便携营养袋回复生命值 + + + + + + + + + + + + + + + + + + + + + diff --git a/BetterGenshinImpact/View/Pages/View/PathingConfigView.xaml b/BetterGenshinImpact/View/Pages/View/PathingConfigView.xaml index 06c76a95..754c9c8a 100644 --- a/BetterGenshinImpact/View/Pages/View/PathingConfigView.xaml +++ b/BetterGenshinImpact/View/Pages/View/PathingConfigView.xaml @@ -231,6 +231,35 @@ TextWrapping="NoWrap" /> + + + + + + + + + + + + + + + + + + + diff --git a/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml b/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml index be3c980e..9c2bbb18 100644 --- a/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml +++ b/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml @@ -75,6 +75,30 @@ Grid.Column="1" IsChecked="{Binding PathingConfig.AutoPickEnabled}" /> + + + + + + + + + + + + +