mirror of
https://github.com/babalae/better-genshin-impact
synced 2025-01-08 11:57:53 +08:00
add auto cook #266
This commit is contained in:
parent
a801bb2c4f
commit
a84c94c5ce
@ -50,5 +50,11 @@
|
||||
Height="23"
|
||||
Click="GenAvatarData"
|
||||
Content="生成侧面头像数据集" />
|
||||
<Button Canvas.Left="10"
|
||||
Canvas.Top="190"
|
||||
Width="100"
|
||||
Height="23"
|
||||
Click="AutoCookTestCase"
|
||||
Content="自动烹饪图像测试" />
|
||||
</Canvas>
|
||||
</Window>
|
@ -60,4 +60,9 @@ public partial class MainWindow : Window
|
||||
{
|
||||
AvatarClassifyGen.GenAll();
|
||||
}
|
||||
|
||||
private void AutoCookTestCase(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AutoCookTest.Test();
|
||||
}
|
||||
}
|
||||
|
17
BetterGenshinImpact.Test/Simple/AutoCookTest.cs
Normal file
17
BetterGenshinImpact.Test/Simple/AutoCookTest.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace BetterGenshinImpact.Test.Simple;
|
||||
|
||||
internal class AutoCookTest
|
||||
{
|
||||
public static void Test()
|
||||
{
|
||||
var img = new Mat(@"E:\HuiTask\更好的原神\自动烹饪\2.png");
|
||||
Cv2.CvtColor(img, img, ColorConversionCodes.BGR2RGB);
|
||||
var img2 = new Mat();
|
||||
// Cv2.InRange(img, new Scalar(255, 192, 64), new Scalar(255, 192, 64), img2);
|
||||
Cv2.InRange(img, new Scalar(255, 255, 192), new Scalar(255, 255, 192), img2);
|
||||
|
||||
Cv2.ImShow("img", img2);
|
||||
}
|
||||
}
|
@ -468,6 +468,12 @@
|
||||
<None Update="GameTask\Common\Element\Assets\1920x1080\submit_icon_exclamation.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="GameTask\Common\Element\Assets\1920x1080\ui_left_top_cook_icon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="GameTask\Common\Element\Assets\1920x1080\ui_lt_cook_icon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="GameTask\Common\Element\Assets\1920x1080\yellow_track_point_28x.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@ -13,6 +13,7 @@ using Fischless.GameCapture;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Serialization;
|
||||
using BetterGenshinImpact.GameTask.AutoCook;
|
||||
|
||||
namespace BetterGenshinImpact.Core.Config;
|
||||
|
||||
@ -90,10 +91,15 @@ public partial class AllConfig : ObservableObject
|
||||
public AutoFishingConfig AutoFishingConfig { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 自动钓鱼配置
|
||||
/// 快速传送配置
|
||||
/// </summary>
|
||||
public QuickTeleportConfig QuickTeleportConfig { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 自动烹饪配置
|
||||
/// </summary>
|
||||
public AutoCookConfig AutoCookConfig { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 自动打牌配置
|
||||
/// </summary>
|
||||
@ -145,6 +151,7 @@ public partial class AllConfig : ObservableObject
|
||||
AutoSkipConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
AutoFishingConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
QuickTeleportConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
AutoCookConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
MacroConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
HotKeyConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
AutoWoodConfig.PropertyChanged += OnAnyPropertyChanged;
|
||||
|
54
BetterGenshinImpact/GameTask/AutoCook/AutoCookTrigger.cs
Normal file
54
BetterGenshinImpact/GameTask/AutoCook/AutoCookTrigger.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using BetterGenshinImpact.Core.Recognition.OpenCv;
|
||||
using BetterGenshinImpact.GameTask.Common.Element.Assets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenCvSharp;
|
||||
using System.Linq;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask.AutoCook;
|
||||
|
||||
public class AutoCookTrigger : ITaskTrigger
|
||||
{
|
||||
private readonly ILogger<AutoCookTrigger> _logger = App.GetLogger<AutoCookTrigger>();
|
||||
|
||||
public string Name => "自动烹饪";
|
||||
public bool IsEnabled { get; set; }
|
||||
public int Priority => 50;
|
||||
public bool IsExclusive { get; set; }
|
||||
|
||||
public void Init()
|
||||
{
|
||||
IsEnabled = TaskContext.Instance().Config.AutoCookConfig.Enabled;
|
||||
IsExclusive = false;
|
||||
}
|
||||
|
||||
public void OnCapture(CaptureContent content)
|
||||
{
|
||||
// 判断是否处于烹饪界面
|
||||
IsExclusive = false;
|
||||
content.CaptureRectArea.Find(ElementAssets.Instance.UiLeftTopCookIcon, foundRectArea =>
|
||||
{
|
||||
IsExclusive = true;
|
||||
var captureRect = TaskContext.Instance().SystemInfo.ScaleMax1080PCaptureRect;
|
||||
using var region = content.CaptureRectArea.DeriveCrop(0, captureRect.Height / 2, captureRect.Width, captureRect.Height / 2);
|
||||
var perfectBarRects = ContoursHelper.FindSpecifyColorRects(region.SrcMat, new Scalar(255, 192, 64), 0, 8);
|
||||
if (perfectBarRects.Count >= 2)
|
||||
{
|
||||
// 点击烹饪按钮
|
||||
var btnList = ContoursHelper.FindSpecifyColorRects(region.SrcMat, new Scalar(255, 255, 192), 12, 12);
|
||||
if (btnList.Count >= 1)
|
||||
{
|
||||
if (btnList.Count > 1)
|
||||
{
|
||||
_logger.LogWarning("自动烹饪:{Text}", "识别到多个结束烹饪按钮");
|
||||
btnList = [.. btnList.OrderByDescending(r => r.Width)];
|
||||
}
|
||||
var btn = btnList[0];
|
||||
var x = btn.X + btn.Width / 2;
|
||||
var y = btn.Y + btn.Height / 2;
|
||||
region.ClickTo(x, y);
|
||||
_logger.LogInformation("自动烹饪:{Text}", "点击结束按钮");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
17
BetterGenshinImpact/GameTask/AutoCook/AutoPickConfig.cs
Normal file
17
BetterGenshinImpact/GameTask/AutoCook/AutoPickConfig.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask.AutoCook;
|
||||
|
||||
/// <summary>
|
||||
///自动烹饪配置
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public partial class AutoCookConfig : ObservableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发器是否启用
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private bool _enabled = false;
|
||||
}
|
@ -1,9 +1,5 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask.AutoPick
|
||||
{
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
@ -16,6 +16,8 @@ public class ElementAssets : BaseAssets<ElementAssets>
|
||||
public RecognitionObject PaimonMenuRo;
|
||||
public RecognitionObject BlueTrackPoint;
|
||||
|
||||
public RecognitionObject UiLeftTopCookIcon;
|
||||
|
||||
private ElementAssets()
|
||||
{
|
||||
// 按钮
|
||||
@ -83,5 +85,15 @@ public class ElementAssets : BaseAssets<ElementAssets>
|
||||
Threshold = 0.6,
|
||||
DrawOnWindow = true
|
||||
}.InitTemplate();
|
||||
|
||||
// 左上角UI元素
|
||||
UiLeftTopCookIcon = new RecognitionObject
|
||||
{
|
||||
Name = "UiLeftTopCookIcon",
|
||||
RecognitionType = RecognitionTypes.TemplateMatch,
|
||||
TemplateImageMat = GameTaskManager.LoadAssetImage(@"Common\Element", "ui_left_top_cook_icon.png"),
|
||||
RegionOfInterest = new Rect(0, 0, (int)(150 * AssetScale), (int)(120 * AssetScale)),
|
||||
DrawOnWindow = false
|
||||
}.InitTemplate();
|
||||
}
|
||||
}
|
||||
|
@ -20,110 +20,111 @@ using BetterGenshinImpact.GameTask.QuickSereniteaPot.Assets;
|
||||
using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
|
||||
using BetterGenshinImpact.View.Drawable;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask
|
||||
namespace BetterGenshinImpact.GameTask;
|
||||
|
||||
internal class GameTaskManager
|
||||
{
|
||||
internal class GameTaskManager
|
||||
public static Dictionary<string, ITaskTrigger>? TriggerDictionary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 一定要在任务上下文初始化完毕后使用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<ITaskTrigger> LoadTriggers()
|
||||
{
|
||||
public static Dictionary<string, ITaskTrigger>? TriggerDictionary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 一定要在任务上下文初始化完毕后使用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<ITaskTrigger> LoadTriggers()
|
||||
ReloadAssets();
|
||||
TriggerDictionary = new Dictionary<string, ITaskTrigger>()
|
||||
{
|
||||
ReloadAssets();
|
||||
TriggerDictionary = new Dictionary<string, ITaskTrigger>()
|
||||
{ "RecognitionTest", new TestTrigger() },
|
||||
{ "GameLoading", new GameLoadingTrigger() },
|
||||
{ "AutoPick", new AutoPick.AutoPickTrigger() },
|
||||
{ "QuickTeleport", new QuickTeleport.QuickTeleportTrigger() },
|
||||
{ "AutoSkip", new AutoSkip.AutoSkipTrigger() },
|
||||
{ "AutoFishing", new AutoFishing.AutoFishingTrigger() },
|
||||
{ "AutoCook", new AutoCook.AutoCookTrigger() }
|
||||
};
|
||||
|
||||
var loadedTriggers = TriggerDictionary.Values.ToList();
|
||||
|
||||
loadedTriggers.ForEach(i => i.Init());
|
||||
|
||||
loadedTriggers = loadedTriggers.OrderByDescending(i => i.Priority).ToList();
|
||||
return loadedTriggers;
|
||||
}
|
||||
|
||||
public static void RefreshTriggerConfigs()
|
||||
{
|
||||
if (TriggerDictionary is { Count: > 0 })
|
||||
{
|
||||
TriggerDictionary["AutoPick"].IsEnabled = TaskContext.Instance().Config.AutoPickConfig.Enabled;
|
||||
// 用于刷新AutoPick的黑白名单
|
||||
TriggerDictionary["AutoPick"].Init();
|
||||
TriggerDictionary["AutoSkip"].IsEnabled = TaskContext.Instance().Config.AutoSkipConfig.Enabled;
|
||||
TriggerDictionary["AutoFishing"].IsEnabled = TaskContext.Instance().Config.AutoFishingConfig.Enabled;
|
||||
// 钓鱼有很多变量要初始化,直接重新newZA
|
||||
if (TriggerDictionary["AutoFishing"].IsEnabled == false)
|
||||
{
|
||||
{ "RecognitionTest", new TestTrigger() },
|
||||
{ "GameLoading", new GameLoadingTrigger() },
|
||||
{ "AutoPick", new AutoPick.AutoPickTrigger() },
|
||||
{ "QuickTeleport", new QuickTeleport.QuickTeleportTrigger() },
|
||||
{ "AutoSkip", new AutoSkip.AutoSkipTrigger() },
|
||||
{ "AutoFishing", new AutoFishing.AutoFishingTrigger() }
|
||||
};
|
||||
TriggerDictionary["AutoFishing"].Init();
|
||||
}
|
||||
TriggerDictionary["QuickTeleport"].IsEnabled = TaskContext.Instance().Config.QuickTeleportConfig.Enabled;
|
||||
TriggerDictionary["GameLoading"].Init();
|
||||
TriggerDictionary["AutoCook"].Init();
|
||||
// 清理画布
|
||||
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(new object(), "RemoveAllButton", new object(), ""));
|
||||
VisionContext.Instance().DrawContent.ClearAll();
|
||||
}
|
||||
ReloadAssets();
|
||||
}
|
||||
|
||||
var loadedTriggers = TriggerDictionary.Values.ToList();
|
||||
public static void ReloadAssets()
|
||||
{
|
||||
AutoPickAssets.DestroyInstance();
|
||||
AutoSkipAssets.DestroyInstance();
|
||||
AutoFishingAssets.DestroyInstance();
|
||||
QuickTeleportAssets.DestroyInstance();
|
||||
AutoWoodAssets.DestroyInstance();
|
||||
AutoGeniusInvokationAssets.DestroyInstance();
|
||||
AutoFightAssets.DestroyInstance();
|
||||
ElementAssets.DestroyInstance();
|
||||
QuickSereniteaPotAssets.DestroyInstance();
|
||||
GameLoadingAssets.DestroyInstance();
|
||||
}
|
||||
|
||||
loadedTriggers.ForEach(i => i.Init());
|
||||
|
||||
loadedTriggers = loadedTriggers.OrderByDescending(i => i.Priority).ToList();
|
||||
return loadedTriggers;
|
||||
/// <summary>
|
||||
/// 获取素材图片并缩放
|
||||
/// todo 支持多语言
|
||||
/// </summary>
|
||||
/// <param name="featName">任务名称</param>
|
||||
/// <param name="assertName">素材文件名</param>
|
||||
/// <param name="flags"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FileNotFoundException"></exception>
|
||||
public static Mat LoadAssetImage(string featName, string assertName, ImreadModes flags = ImreadModes.Color)
|
||||
{
|
||||
var info = TaskContext.Instance().SystemInfo;
|
||||
var assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\{info.GameScreenSize.Width}x{info.GameScreenSize.Height}");
|
||||
if (!Directory.Exists(assetsFolder))
|
||||
{
|
||||
assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\1920x1080");
|
||||
}
|
||||
|
||||
public static void RefreshTriggerConfigs()
|
||||
if (!Directory.Exists(assetsFolder))
|
||||
{
|
||||
if (TriggerDictionary is { Count: > 0 })
|
||||
{
|
||||
TriggerDictionary["AutoPick"].IsEnabled = TaskContext.Instance().Config.AutoPickConfig.Enabled;
|
||||
// 用于刷新AutoPick的黑白名单
|
||||
TriggerDictionary["AutoPick"].Init();
|
||||
TriggerDictionary["AutoSkip"].IsEnabled = TaskContext.Instance().Config.AutoSkipConfig.Enabled;
|
||||
TriggerDictionary["AutoFishing"].IsEnabled = TaskContext.Instance().Config.AutoFishingConfig.Enabled;
|
||||
// 钓鱼有很多变量要初始化,直接重新newZA
|
||||
if (TriggerDictionary["AutoFishing"].IsEnabled == false)
|
||||
{
|
||||
TriggerDictionary["AutoFishing"].Init();
|
||||
}
|
||||
TriggerDictionary["QuickTeleport"].IsEnabled = TaskContext.Instance().Config.QuickTeleportConfig.Enabled;
|
||||
TriggerDictionary["GameLoading"].Init();
|
||||
// 清理画布
|
||||
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(new object(), "RemoveAllButton", new object(), ""));
|
||||
VisionContext.Instance().DrawContent.ClearAll();
|
||||
}
|
||||
ReloadAssets();
|
||||
throw new FileNotFoundException($"未找到{featName}的素材文件夹");
|
||||
}
|
||||
|
||||
public static void ReloadAssets()
|
||||
var filePath = Path.Combine(assetsFolder, assertName);
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
AutoPickAssets.DestroyInstance();
|
||||
AutoSkipAssets.DestroyInstance();
|
||||
AutoFishingAssets.DestroyInstance();
|
||||
QuickTeleportAssets.DestroyInstance();
|
||||
AutoWoodAssets.DestroyInstance();
|
||||
AutoGeniusInvokationAssets.DestroyInstance();
|
||||
AutoFightAssets.DestroyInstance();
|
||||
ElementAssets.DestroyInstance();
|
||||
QuickSereniteaPotAssets.DestroyInstance();
|
||||
GameLoadingAssets.DestroyInstance();
|
||||
throw new FileNotFoundException($"未找到{featName}中的{assertName}文件");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取素材图片并缩放
|
||||
/// todo 支持多语言
|
||||
/// </summary>
|
||||
/// <param name="featName">任务名称</param>
|
||||
/// <param name="assertName">素材文件名</param>
|
||||
/// <param name="flags"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FileNotFoundException"></exception>
|
||||
public static Mat LoadAssetImage(string featName, string assertName, ImreadModes flags = ImreadModes.Color)
|
||||
var mat = Mat.FromStream(File.OpenRead(filePath), flags);
|
||||
if (info.GameScreenSize.Width != 1920)
|
||||
{
|
||||
var info = TaskContext.Instance().SystemInfo;
|
||||
var assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\{info.GameScreenSize.Width}x{info.GameScreenSize.Height}");
|
||||
if (!Directory.Exists(assetsFolder))
|
||||
{
|
||||
assetsFolder = Global.Absolute($@"GameTask\{featName}\Assets\1920x1080");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(assetsFolder))
|
||||
{
|
||||
throw new FileNotFoundException($"未找到{featName}的素材文件夹");
|
||||
}
|
||||
|
||||
var filePath = Path.Combine(assetsFolder, assertName);
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new FileNotFoundException($"未找到{featName}中的{assertName}文件");
|
||||
}
|
||||
|
||||
var mat = Mat.FromStream(File.OpenRead(filePath), flags);
|
||||
if (info.GameScreenSize.Width != 1920)
|
||||
{
|
||||
mat = ResizeHelper.Resize(mat, info.AssetScale);
|
||||
}
|
||||
|
||||
return mat;
|
||||
mat = ResizeHelper.Resize(mat, info.AssetScale);
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
|
@ -750,7 +750,7 @@
|
||||
<ui:TextBlock Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
FontTypography="Body"
|
||||
Text="活动音游"
|
||||
Text="活动音游(限时)"
|
||||
TextWrapping="Wrap" />
|
||||
<ui:TextBlock Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
|
@ -597,6 +597,30 @@
|
||||
</StackPanel>
|
||||
</ui:CardExpander>
|
||||
|
||||
<!-- 自动烹饪 -->
|
||||
<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Fireplace24}">
|
||||
<ui:CardControl.Header>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<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}"
|
||||
TextWrapping="Wrap">
|
||||
手动烹饪时,自动在完美状态下结束烹饪(不用的时候请关闭)
|
||||
</ui:TextBlock>
|
||||
</Grid>
|
||||
</ui:CardControl.Header>
|
||||
<ui:ToggleSwitch Margin="0,0,36,0" IsChecked="{Binding Config.AutoCookConfig.Enabled, Mode=TwoWay}" />
|
||||
</ui:CardControl>
|
||||
|
||||
<!-- 一键战斗 -->
|
||||
<!--<ui:CardExpander Margin="0,0,0,12" ContentPadding="0" Icon="{ui:SymbolIcon ArrowSync24}">
|
||||
<ui:CardExpander.Header>
|
||||
|
Loading…
Reference in New Issue
Block a user