Merge remote-tracking branch 'origin/main'

This commit is contained in:
zjl
2025-01-03 20:14:07 +08:00
18 changed files with 745 additions and 151 deletions

View File

@@ -19,17 +19,17 @@ public class AvatarClassifyGen
// 读取基础图像
// List<string> sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "*.png", SearchOption.TopDirectoryOnly).ToList();
// 只用一个图像
List<string> sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Chasca.png", SearchOption.TopDirectoryOnly).ToList();
List<string> sideImageFiles2 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Olorun.png", SearchOption.TopDirectoryOnly).ToList();
List<string> sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_HutaoCostumeWinter.png", SearchOption.TopDirectoryOnly).ToList();
List<string> sideImageFiles2 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Iansan.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles2);
// List<string> sideImageFiles3 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_NilouCostumeFairy.png", SearchOption.TopDirectoryOnly).ToList();
// sideImageFiles.AddRange(sideImageFiles3);
// List<string> sideImageFiles4 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Kachina.png", SearchOption.TopDirectoryOnly).ToList();
// sideImageFiles.AddRange(sideImageFiles4);
// List<string> sideImageFiles5 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Mualani.png", SearchOption.TopDirectoryOnly).ToList();
// sideImageFiles.AddRange(sideImageFiles5);
// List<string> sideImageFiles6 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Kinich.png", SearchOption.TopDirectoryOnly).ToList();
// sideImageFiles.AddRange(sideImageFiles6);
List<string> sideImageFiles3 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Citlali.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles3);
List<string> sideImageFiles4 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Lanyan.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles4);
List<string> sideImageFiles5 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_XianglingCostumeWinter.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles5);
List<string> sideImageFiles6 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Mavuika.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles6);
// 生成训练集
GenTo(sideImageFiles, Path.Combine(BaseDir, @"dateset\train"), 200);

View File

@@ -27,9 +27,17 @@ public class AvatarClassifyTransparentGen
// 读取基础图像
// List<string> sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "*.png", SearchOption.TopDirectoryOnly).ToList();
// 只用一个图像
List<string> sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_Chasca.png", SearchOption.TopDirectoryOnly).ToList();
List<string> sideImageFiles2 = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_Olorun.png", SearchOption.TopDirectoryOnly).ToList();
List<string> sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_HutaoCostumeWinter.png", SearchOption.TopDirectoryOnly).ToList();
List<string> sideImageFiles2 = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_Iansan.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles2);
List<string> sideImageFiles3 = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_Citlali.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles3);
List<string> sideImageFiles4 = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_Lanyan.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles4);
List<string> sideImageFiles5 = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_XianglingCostumeWinter.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles5);
List<string> sideImageFiles6 = Directory.GetFiles(Path.Combine(BaseDir, SideSrcTransportDir), "UI_AvatarIcon_Side_Mavuika.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles6);
// 生成训练集
GenTo(sideImageFiles, Path.Combine(BaseDir, @"dateset\train"), 200);
// 生成测试集

View File

@@ -10,7 +10,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationIcon>Assets\Images\logo.ico</ApplicationIcon>
<AssemblyName>BetterGI</AssemblyName>
<AssemblyVersion>0.38.1</AssemblyVersion>
<AssemblyVersion>0.39.1</AssemblyVersion>
<Platforms>x64</Platforms>
<DebugType>embedded</DebugType>
</PropertyGroup>
@@ -128,6 +128,9 @@
<None Update="GameTask\AutoWood\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\AutoMusicGame\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="GameTask\GameLoading\Assets\1920x1080\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View File

@@ -1,5 +1,8 @@
using Fischless.WindowsInput;
using System;
using BetterGenshinImpact.GameTask.Common;
using Microsoft.Extensions.Logging;
using Vanara.PInvoke;
namespace BetterGenshinImpact.Core.Simulator;
@@ -13,4 +16,26 @@ public class Simulation
{
return new PostMessageSimulator(hWnd);
}
}
public static void ReleaseAllKey()
{
foreach (User32.VK key in Enum.GetValues(typeof(User32.VK)))
{
// 检查键是否被按下
if (IsKeyDown(key)) // 强制转换 VK 枚举为 int
{
TaskControl.Logger.LogDebug($"解除{key}的按下状态.");
SendInput.Keyboard.KeyUp(key);
}
}
}
private static bool IsKeyDown(User32.VK key)
{
// 获取按键状态
var state = User32.GetAsyncKeyState((int)key);
// 检查高位是否为 1表示按键被按下
return (state & 0x8000) != 0;
}
}

View File

@@ -98,7 +98,6 @@ public class AutoDomainTask : ISoloTask
}
}
}
await Delay(2000, ct);
@@ -118,13 +117,13 @@ public class AutoDomainTask : ISoloTask
var combatScenes = new CombatScenes().InitializeTeam(CaptureToRectArea());
// 前置进入秘境
EnterDomain();
await EnterDomain();
for (var i = 0; i < _taskParam.DomainRoundNum; i++)
{
// 0. 关闭秘境提示
Logger.LogDebug("0. 关闭秘境提示");
CloseDomainTip();
await CloseDomainTip();
// 队伍没初始化成功则重试
RetryTeamInit(combatScenes);
@@ -221,15 +220,37 @@ public class AutoDomainTask : ISoloTask
await Delay(1000, _ct);
await Bv.WaitForMainUi(_ct);
await Delay(1000, _ct);
var walkKey = User32.VK.VK_W;
if (MapLazyAssets.Instance.DomainBackwardList.Contains(_taskParam.DomainName))
if ("芬德尼尔之顶".Equals(_taskParam.DomainName))
{
walkKey = User32.VK.VK_S;
Simulation.SendInput.Keyboard.KeyDown(VK.VK_S);
Thread.Sleep(3000);
Simulation.SendInput.Keyboard.KeyUp(VK.VK_S);
}
else if ("无妄引咎密宫".Equals(_taskParam.DomainName))
{
Simulation.SendInput.Keyboard.KeyDown(VK.VK_W);
Thread.Sleep(500);
Simulation.SendInput.Keyboard.KeyUp(VK.VK_W);
Thread.Sleep(100);
Simulation.SendInput.Keyboard.KeyDown(VK.VK_A);
Thread.Sleep(1600);
Simulation.SendInput.Keyboard.KeyUp(VK.VK_A);
}
else if ("苍白的遗荣".Equals(_taskParam.DomainName))
{
Simulation.SendInput.Keyboard.KeyDown(VK.VK_W);
Thread.Sleep(1000);
Simulation.SendInput.Keyboard.KeyUp(VK.VK_W);
}
else
{
Simulation.SendInput.Keyboard.KeyDown(VK.VK_W);
Thread.Sleep(3000);
Simulation.SendInput.Keyboard.KeyUp(VK.VK_W);
}
Simulation.SendInput.Keyboard.KeyDown(walkKey);
Thread.Sleep(3500);
Simulation.SendInput.Keyboard.KeyUp(walkKey);
await Delay(3000, _ct); // 站稳
}
else
{
@@ -256,7 +277,7 @@ public class AutoDomainTask : ISoloTask
return true;
}
private void EnterDomain()
private async Task EnterDomain()
{
var fightAssets = AutoFightContext.Instance.FightAssets;
@@ -267,7 +288,7 @@ public class AutoDomainTask : ISoloTask
Simulation.SendInput.Keyboard.KeyPress(VK.VK_F);
Logger.LogInformation("自动秘境:{Text}", "进入秘境");
// 秘境开门动画 5s
Sleep(5000, _ct);
await Delay(5000, _ct);
}
int retryTimes = 0, clickCount = 0;
@@ -281,14 +302,14 @@ public class AutoDomainTask : ISoloTask
clickCount++;
}
Sleep(1500, _ct);
await Delay(1500, _ct);
}
// 载入动画
Sleep(3000, _ct);
await Delay(3000, _ct);
}
private void CloseDomainTip()
private async Task CloseDomainTip()
{
// 2min的载入时间总够了吧
var retryTimes = 0;
@@ -298,16 +319,16 @@ public class AutoDomainTask : ISoloTask
using var cactRectArea = CaptureToRectArea().Find(AutoFightContext.Instance.FightAssets.ClickAnyCloseTipRa);
if (!cactRectArea.IsEmpty())
{
Sleep(1000, _ct);
await Delay(1000, _ct);
cactRectArea.Click();
break;
}
// todo 添加小地图角标位置检测 防止有人手点了
Sleep(1000, _ct);
await Delay(1000, _ct);
}
Sleep(1500, _ct);
await Delay(1500, _ct);
}
private List<CombatCommand> FindCombatScriptAndSwitchAvatar(CombatScenes combatScenes)

View File

@@ -1620,7 +1620,8 @@
"卡齐纳",
"卡齐那",
"卡其那",
"冲天钻钻"
"冲天钻钻",
"岩莉莉"
],
"burstCD": 18,
"id": "10000100",
@@ -1634,7 +1635,8 @@
"基尼奇",
"Kinich",
"基哥",
"基尼齐"
"基尼齐",
"蜘蛛侠"
],
"burstCD": 18,
"id": "10000101",
@@ -1684,7 +1686,8 @@
"恰斯卡",
"Chasca",
"武卡",
"调停人"
"调停人",
"鸟人"
],
"burstCD": 15,
"id": "10000104",
@@ -1696,9 +1699,10 @@
{
"alias": [
"欧洛伦",
"Olorun",
"Ororon",
"庇笛",
"孙子",
"大孙子",
"蝙蝠侠"
],
"burstCD": 15,
@@ -1707,5 +1711,55 @@
"nameEn": "Olorun",
"skillCD": 15,
"weapon": "12"
},
{
"alias": [
"玛薇卡",
"Mavuika",
"火神",
"马薇卡",
"玛维卡",
"马维卡"
],
"burstCD": 18,
"id": "10000106",
"name": "玛薇卡",
"nameEn": "Mavuika",
"skillCD": 15,
"weapon": "11"
},
{
"alias": [
"茜特菈莉",
"Citlali",
"西特菈莉",
"西特拉莉",
"茜特拉莉",
"西特拉利",
"黑曜石奶奶",
"黑曜石",
"奶奶",
"老伴"
],
"burstCD": 15,
"id": "10000107",
"name": "茜特菈莉",
"nameEn": "Citlali",
"skillCD": 16,
"weapon": "10"
},
{
"alias": [
"蓝砚",
"蓝燕",
"兰砚",
"兰燕"
],
"burstCD": 15,
"id": "10000108",
"name": "蓝砚",
"nameEn": "Lanyan",
"skillCD": 16,
"weapon": "10"
}
]

View File

@@ -1787,6 +1787,75 @@
}
]
},
{
"id": 1214,
"nameEn": "mualani",
"type": "character",
"name": "玛拉妮",
"hp": 10,
"energy": 2,
"element": "水元素",
"weapon": "法器",
"skills": [
{
"nameEn": "cooling_treatment",
"name": "降温处理",
"skillTag": [
"普通攻击"
],
"cost": [
{
"id": 1102,
"nameEn": "hydro",
"type": "水元素",
"count": 1
},
{
"id": 1109,
"nameEn": "unaligned_element",
"type": "无色元素",
"count": 2
}
]
},
{
"nameEn": "surfshark_wavebreaker",
"name": "踏鲨破浪",
"skillTag": [
"元素战技"
],
"cost": [
{
"id": 1102,
"nameEn": "hydro",
"type": "水元素",
"count": 2
}
]
},
{
"nameEn": "boomsharkalaka",
"name": "爆瀑飞弹",
"skillTag": [
"元素爆发"
],
"cost": [
{
"id": 1102,
"nameEn": "hydro",
"type": "水元素",
"count": 3
},
{
"id": 1110,
"nameEn": "energy",
"type": "充能",
"count": 2
}
]
}
]
},
{
"id": 1301,
"nameEn": "diluc",
@@ -3482,6 +3551,75 @@
}
]
},
{
"id": 1412,
"nameEn": "clorinde",
"type": "character",
"name": "克洛琳德",
"hp": 10,
"energy": 2,
"element": "雷元素",
"weapon": "单手剑",
"skills": [
{
"nameEn": "oath_of_hunting_shadows",
"name": "逐影之誓",
"skillTag": [
"普通攻击"
],
"cost": [
{
"id": 1104,
"nameEn": "electro",
"type": "雷元素",
"count": 1
},
{
"id": 1109,
"nameEn": "unaligned_element",
"type": "无色元素",
"count": 2
}
]
},
{
"nameEn": "hunters_vigil",
"name": "狩夜之巡",
"skillTag": [
"元素战技"
],
"cost": [
{
"id": 1104,
"nameEn": "electro",
"type": "雷元素",
"count": 2
}
]
},
{
"nameEn": "last_lightfall",
"name": "残光将终",
"skillTag": [
"元素爆发"
],
"cost": [
{
"id": 1104,
"nameEn": "electro",
"type": "雷元素",
"count": 3
},
{
"id": 1110,
"nameEn": "energy",
"type": "充能",
"count": 2
}
]
}
]
},
{
"id": 1501,
"nameEn": "sucrose",
@@ -7220,6 +7358,75 @@
}
]
},
{
"id": 2603,
"nameEn": "golden_wolflord",
"type": "character",
"name": "黄金王兽",
"hp": 10,
"energy": 2,
"element": "岩元素",
"weapon": "其他武器",
"skills": [
{
"nameEn": "wolflords_strike",
"name": "王狼直击",
"skillTag": [
"普通攻击"
],
"cost": [
{
"id": 1106,
"nameEn": "geo",
"type": "岩元素",
"count": 1
},
{
"id": 1109,
"nameEn": "unaligned_element",
"type": "无色元素",
"count": 2
}
]
},
{
"nameEn": "howling_riftcall",
"name": "兽境轰召",
"skillTag": [
"元素战技"
],
"cost": [
{
"id": 1106,
"nameEn": "geo",
"type": "岩元素",
"count": 3
}
]
},
{
"nameEn": "golden_cankerbind",
"name": "黄金侵绞",
"skillTag": [
"元素爆发"
],
"cost": [
{
"id": 1106,
"nameEn": "geo",
"type": "岩元素",
"count": 3
},
{
"id": 1110,
"nameEn": "energy",
"type": "充能",
"count": 2
}
]
}
]
},
{
"id": 2701,
"nameEn": "jadeplume_terrorshroom",
@@ -7450,74 +7657,5 @@
"cost": []
}
]
},
{
"id": 4608,
"nameEn": "golden_wolflord",
"type": "character",
"name": "黄金王兽",
"hp": 40,
"energy": 2,
"element": "岩元素",
"weapon": "其他武器",
"skills": [
{
"nameEn": "wolflords_strike",
"name": "王狼直击",
"skillTag": [
"普通攻击"
],
"cost": [
{
"id": 1106,
"nameEn": "geo",
"type": "岩元素",
"count": 1
},
{
"id": 1109,
"nameEn": "unaligned_element",
"type": "无色元素",
"count": 2
}
]
},
{
"nameEn": "howling_riftcall",
"name": "兽境轰召",
"skillTag": [
"元素战技"
],
"cost": [
{
"id": 1106,
"nameEn": "geo",
"type": "岩元素",
"count": 3
}
]
},
{
"nameEn": "golden_cankerbind",
"name": "黄金侵绞",
"skillTag": [
"元素爆发"
],
"cost": [
{
"id": 1106,
"nameEn": "geo",
"type": "岩元素",
"count": 3
},
{
"id": 1110,
"nameEn": "energy",
"type": "充能",
"count": 2
}
]
}
]
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,46 @@
using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.GameTask.Model;
using BetterGenshinImpact.Helpers.Extensions;
using OpenCvSharp;
namespace BetterGenshinImpact.GameTask.AutoMusicGame.Assets;
public class AutoMusicAssets : BaseAssets<AutoMusicAssets>
{
public RecognitionObject UiLeftTopAlbumIcon;
public RecognitionObject BtnPause;
public RecognitionObject AlbumMusicComplate;
public RecognitionObject BtnList;
private AutoMusicAssets()
{
UiLeftTopAlbumIcon = new RecognitionObject
{
Name = "UiLeftTopAlbumIcon",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage(@"AutoMusicGame", "ui_left_top_album_icon.png"),
RegionOfInterest = new Rect(0, 0, (int)(150 * AssetScale), (int)(120 * AssetScale)),
}.InitTemplate();
BtnPause = new RecognitionObject
{
Name = "BtnPause",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage(@"AutoMusicGame", "btn_pause.png"),
RegionOfInterest = CaptureRect.CutRightTop(0.2, 0.2),
}.InitTemplate();
AlbumMusicComplate = new RecognitionObject
{
Name = "AlbumMusicComplate",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage(@"AutoMusicGame", "album_music_complate.png"),
RegionOfInterest = new Rect( (int)(900 * AssetScale),(int)(320 * AssetScale), (int)(100 * AssetScale), (int)(80 * AssetScale)),
}.InitTemplate();
BtnList = new RecognitionObject
{
Name = "BtnList",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage(@"AutoMusicGame", "btn_list.png"),
RegionOfInterest = CaptureRect.CutRightBottom(0.4, 0.2),
}.InitTemplate();
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.GameTask.AutoMusicGame.Assets;
using BetterGenshinImpact.GameTask.Common.BgiVision;
using BetterGenshinImpact.GameTask.Model.Area;
using Microsoft.Extensions.Logging;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
namespace BetterGenshinImpact.GameTask.AutoMusicGame;
/// <summary>
/// 自动音乐专辑
/// </summary>
public class AutoAlbumTask(AutoMusicGameParam taskParam) : ISoloTask
{
public string Name => "自动音游专辑";
private AutoMusicGameTask _autoMusicGameTask = new AutoMusicGameTask(taskParam);
public async Task Start(CancellationToken ct)
{
try
{
AutoMusicGameTask.Init();
Logger.LogInformation("开始自动演奏整个专辑未完成的音乐");
await StartOneAlbum(ct);
}
catch (Exception e)
{
Logger.LogError("自动音乐专辑任务异常:{Msg}", e.Message);
}
}
public async Task StartOneAlbum(CancellationToken ct)
{
using var iconRa = CaptureToRectArea().Find(AutoMusicAssets.Instance.UiLeftTopAlbumIcon);
if (!iconRa.IsExist())
{
throw new Exception("当前未处于专辑界面,请在专辑界面运行本任务");
}
// 12个音乐
for (int i = 0; i < 13; i++)
{
using var doneRa = CaptureToRectArea().Find(AutoMusicAssets.Instance.AlbumMusicComplate);
if (doneRa.IsExist())
{
Logger.LogInformation("当前乐曲{Num}所有奖励已领取,切换下一首", i + 1);
GameCaptureRegion.GameRegion1080PPosClick(310, 220);
await Delay(800, ct);
continue;
}
Logger.LogInformation("当前乐曲{Num}存在未领取奖励,前往演奏", i + 1);
Bv.ClickWhiteConfirmButton(CaptureToRectArea());
await Delay(800, ct);
// 点击传说
GameCaptureRegion.GameRegion1080PPosClick(1400, 600);
await Delay(200, ct);
// 演奏
Bv.ClickWhiteConfirmButton(CaptureToRectArea());
await Delay(500, ct);
CancellationTokenSource cts = new();
ct.Register(cts.Cancel);
// 演奏结束检查任务
var checkTask = Task.Run(async () =>
{
while (!cts.Token.IsCancellationRequested)
{
await Delay(5000, ct); // n秒检查一次
using var listRa = CaptureToRectArea().Find(AutoMusicAssets.Instance.BtnList);
if (listRa.IsExist())
{
listRa.Click();
return;
}
}
}, cts.Token);
// 演奏任务
var musicTask = _autoMusicGameTask.StartWithOutInit(cts.Token);
// 等待任意一个任务完成
await Task.WhenAny(checkTask, musicTask);
await cts.CancelAsync();
Logger.LogInformation("当前乐曲{Num}演奏结束", i + 1);
await Delay(2000, ct);
await Bv.WaitUntilFound(AutoMusicAssets.Instance.UiLeftTopAlbumIcon, ct);
Logger.LogInformation("切换下一首");
GameCaptureRegion.GameRegion1080PPosClick(310, 220);
await Delay(800, ct);
}
Logger.LogInformation("当前专辑所有乐曲演奏结束");
}
}

View File

@@ -15,47 +15,73 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
{
public string Name => "自动音游";
// private readonly ConcurrentDictionary<User32.VK, int> _keyX = new()
// {
// [User32.VK.VK_A] = 417,
// [User32.VK.VK_S] = 632,
// [User32.VK.VK_D] = 846,
// [User32.VK.VK_J] = 1065,
// [User32.VK.VK_K] = 1282,
// [User32.VK.VK_L] = 1500
// };
//
// private readonly int _keyY = 916;
private readonly ConcurrentDictionary<User32.VK, int> _keyX = new()
{
[User32.VK.VK_A] = 417,
[User32.VK.VK_S] = 632,
[User32.VK.VK_D] = 846,
[User32.VK.VK_J] = 1065,
[User32.VK.VK_K] = 1282,
[User32.VK.VK_L] = 1500
[User32.VK.VK_S] = 628,
[User32.VK.VK_D] = 844,
[User32.VK.VK_J] = 1061,
[User32.VK.VK_K] = 1277,
[User32.VK.VK_L] = 1493
};
private readonly int _keyY = 916;
private readonly int _keyY = 921;
private readonly IntPtr _hWnd = TaskContext.Instance().GameHandle;
public Task Start(CancellationToken ct)
public async Task Start(CancellationToken ct)
{
Init();
var assetScale = TaskContext.Instance().SystemInfo.AssetScale;
var taskFactory = new TaskFactory();
var taskList = new List<Task>();
// 计算按键位置
var gameCaptureRegion = CaptureToRectArea();
foreach (var keyValuePair in _keyX)
{
var (x, y) = gameCaptureRegion.ConvertPositionToGameCaptureRegion((int)(keyValuePair.Value * assetScale), (int)(_keyY * assetScale));
// 添加任务
taskList.Add(taskFactory.StartNew(() => DoWhitePressWin32(ct, keyValuePair.Key, new Point(x, y))));
}
Task.WaitAll([.. taskList]);
return Task.CompletedTask;
await StartWithOutInit(ct);
}
private void DoWhitePressWin32(CancellationToken ct, User32.VK key, Point point)
public async Task StartWithOutInit(CancellationToken ct)
{
try
{
Logger.LogInformation("开始自动演奏");
var assetScale = TaskContext.Instance().SystemInfo.AssetScale;
// var taskFactory = new TaskFactory();
var taskList = new List<Task>();
// 计算按键位置
var gameCaptureRegion = CaptureToRectArea();
foreach (var keyValuePair in _keyX)
{
var (x, y) = gameCaptureRegion.ConvertPositionToGameCaptureRegion((int)(keyValuePair.Value * assetScale), (int)(_keyY * assetScale));
// 添加任务
taskList.Add(Task.Run(async () => await DoWhitePressWin32(ct, keyValuePair.Key, new Point(x, y)), ct));
}
await Task.WhenAll(taskList);
}
finally
{
Simulation.ReleaseAllKey();
Logger.LogInformation("结束自动演奏");
}
}
private async Task DoWhitePressWin32(CancellationToken ct, User32.VK key, Point point)
{
while (!ct.IsCancellationRequested)
{
Thread.Sleep(10);
await Task.Delay(5, ct);
// Stopwatch sw = new();
// sw.Start();
var hdc = User32.GetDC(_hWnd);
@@ -67,7 +93,7 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
KeyDown(key);
while (!ct.IsCancellationRequested)
{
Thread.Sleep(10);
await Task.Delay(5, ct);
hdc = User32.GetDC(_hWnd);
c = Gdi32.GetPixel(hdc, point.X, point.Y);
Gdi32.DeleteDC(hdc);
@@ -76,6 +102,7 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
break;
}
}
KeyUp(key);
}
@@ -84,6 +111,121 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
}
}
// private async Task DoWhitePressWin32Default(CancellationToken ct, User32.VK key, Point point)
// {
// while (!ct.IsCancellationRequested)
// {
// await Task.Delay(10, ct);
// var c = GetPixel(point.X, point.Y);
//
// if (c.G < 220)
// {
// KeyDown(key);
// while (!ct.IsCancellationRequested)
// {
// Thread.Sleep(10);
// c = GetPixel(point.X, point.Y);
// if (c.G >= 230 && c.G != 255)
// {
// if (point.X == 417)
// {
// Debug.WriteLine("打断颜色:" + c.R + "," + c.G + "," + c.B);
// }
//
// break;
// }
// }
//
// KeyUp(key);
// }
// }
// }
// private async Task DoWhitePressWin32Default(CancellationToken ct, User32.VK key, Point point)
// {
// while (!ct.IsCancellationRequested)
// {
// await Task.Delay(5, ct);
// var color = GetPixel(point.X, point.Y);
// int r = color.R, g = color.G, b = color.B;
//
// if (r >= 140 && r <= 255 && g >= 100 && g <= 170 && b >= 230 && b <= 255)
// {
// // 按下按键
// KeyDown(key);
//
// int z1 = 0;
// while (z1 < 3)
// {
// await Task.Delay(5, ct);
// color = GetPixel(point.X, point.Y);
// int r1 = color.R, g1 = color.G, b1 = color.B;
// var color2 = GetPixel(point.X + 2, point.Y + 2);
// int r11 = color2.R, g11 = color2.G, b11 = color2.B;
//
// if ((r1 >= 140 && r1 <= 255 && g1 >= 100 && g1 <= 170) || (r11 >= 140 && r11 <= 255 && g11 >= 100 && g11 <= 170))
// {
// continue;
// }
//
// z1++;
// }
//
// Console.WriteLine($"{key} purple1 {r} {g} {b}");
//
// int z2 = 0;
// while (z2 < 10)
// {
// await Task.Delay(5, ct);
// color = GetPixel(point.X, point.Y);
// int r1 = color.R, g1 = color.G, b1 = color.B;
// var color2 = GetPixel(point.X + 2, point.Y + 2);
// int r11 = color2.R, g11 = color2.G, b11 = color2.B;
//
// if (g1 >= 100 && g1 <= 170 || g11 >= 100 && g11 <= 170)
// {
// continue;
// }
//
// z2++;
// }
//
// Console.WriteLine($"{key} purple - 紫键结束 {r} {g} {b}");
// KeyUp(key);
// }
//
// if (r >= 230 && r <= 255 && g >= 170 && g <= 210 && b >= 50 && b <= 120)
// {
// KeyDown(key);
//
// var color2 = GetPixel(point.X, point.Y);
// int r2 = color2.R, g2 = color2.G, b2 = color2.B;
//
//
// while (g2 >= 170 && g2 <= 210 && b2 >= 50 && b2 <= 120)
// {
//
// await Task.Delay(5, ct);
// color2 = GetPixel(point.X, point.Y);
// r2 = color2.R;
// g2 = color2.G;
// b2 = color2.B;
// }
//
// KeyUp(key);
// }
// }
// }
private COLORREF GetPixel(int x, int y)
{
var hdc = User32.GetDC(_hWnd);
var c = Gdi32.GetPixel(hdc, x, y);
Gdi32.DeleteDC(hdc);
return c;
}
private void KeyUp(User32.VK key)
{
Simulation.SendInput.Keyboard.KeyUp(key);
@@ -94,17 +236,21 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
Simulation.SendInput.Keyboard.KeyDown(key);
}
private void Init()
public static void Init()
{
LogScreenResolution();
}
private void LogScreenResolution()
public static void LogScreenResolution()
{
var gameScreenSize = SystemControl.GetGameScreenRect(TaskContext.Instance().GameHandle);
if (gameScreenSize.Width * 9 != gameScreenSize.Height * 16)
{
Logger.LogWarning("游戏窗口分辨率不是 16:9 !当前分辨率为 {Width}x{Height} , 非 16:9 分辨率的游戏可能无法正常使用自动活动音游功能 !", gameScreenSize.Width, gameScreenSize.Height);
Logger.LogError("游戏窗口分辨率不是 16:9 !当前分辨率为 {Width}x{Height} , 非 16:9 分辨率的游戏无法正常使用自动活动音游功能 !", gameScreenSize.Width, gameScreenSize.Height);
throw new Exception("游戏窗口分辨率不是 16:9");
}
Logger.LogInformation("{Name}:回到游戏主界面时记得关闭自动音游任务!", "千音雅集");
Logger.LogWarning("{Name}:默认的样式“轻漾涟漪”是{No}的!需要手动完成几首曲目获得{Money}千音币后兑换并使用胡桃样式“{Hutao}”!", "千音雅集", "不可用", 600, "疏影引蝶映梅红");
}
}
}

View File

@@ -1176,7 +1176,7 @@
</StackPanel>
</ui:CardExpander>-->
<!-- 动音游(限时,已失效) -->
<!-- 动音游 -->
<ui:CardControl Margin="0,0,0,12"
Icon="{ui:SymbolIcon MusicNote224}">
<ui:CardControl.Header>
@@ -1188,7 +1188,7 @@
<ui:TextBlock Grid.Row="0"
Grid.Column="0"
FontTypography="Body"
Text="自动音游"
Text="自动音游(千音雅集)"
TextWrapping="Wrap" />
<ui:TextBlock Grid.Row="1"
Grid.Column="0"
@@ -1209,6 +1209,42 @@
EnableContent="{Binding SwitchAutoMusicGameButtonText}"
IsChecked="{Binding SwitchAutoMusicGameEnabled}" />
</ui:CardControl>
<!-- 自动音游专辑 -->
<ui:CardControl Margin="0,0,0,12">
<ui:CardControl.Icon>
<ui:FontIcon Glyph="&#xf89f;" Style="{StaticResource FaFontIconStyle}" />
</ui:CardControl.Icon>
<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">
进入专辑界面使用,自动演奏未完成乐曲 -
<Hyperlink Command="{Binding GoToAutoMusicGameUrlCommand}"
Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}">
点击查看使用教程
</Hyperlink>
</ui:TextBlock>
</Grid>
</ui:CardControl.Header>
<controls:TwoStateButton Margin="0,0,36,0"
DisableCommand="{Binding StopSoloTaskCommand}"
DisableContent="停止"
EnableCommand="{Binding SwitchAutoAlbumCommand}"
EnableContent="{Binding SwitchAutoAlbumButtonText}"
IsChecked="{Binding SwitchAutoAlbumEnabled}" />
</ui:CardControl>
<!--<ui:CardExpander Margin="0,0,0,12" ContentPadding="0" Icon="{ui:SymbolIcon Accessibility24}">

View File

@@ -382,6 +382,13 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel
Config.HotKeyConfig.AutoDomainHotkeyType,
(_, _) => { SwitchSoloTask(_taskSettingsPageViewModel.SwitchAutoDomainCommand); }
));
soloTaskDirectory.Children.Add(new HotKeySettingModel(
"启动/停止自动音游",
nameof(Config.HotKeyConfig.AutoMusicGameHotkey),
Config.HotKeyConfig.AutoMusicGameHotkey,
Config.HotKeyConfig.AutoMusicGameHotkeyType,
(_, _) => { SwitchSoloTask(_taskSettingsPageViewModel.SwitchAutoMusicGameCommand); }
));
macroDirectory.Children.Add(new HotKeySettingModel(
"快捷点击原神内确认按钮",
@@ -515,13 +522,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel
);
HotKeySettingModels.Add(debugDirectory);
soloTaskDirectory.Children.Add(new HotKeySettingModel(
"启动/停止自动活动音游",
nameof(Config.HotKeyConfig.AutoMusicGameHotkey),
Config.HotKeyConfig.AutoMusicGameHotkey,
Config.HotKeyConfig.AutoMusicGameHotkeyType,
(_, _) => { SwitchSoloTask(_taskSettingsPageViewModel.SwitchAutoMusicGameCommand); }
));
// HotKeySettingModels.Add(new HotKeySettingModel(
// "(测试)启动/停止自动追踪",
// nameof(Config.HotKeyConfig.AutoTrackHotkey),

View File

@@ -39,8 +39,8 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw
private CancellationTokenSource? _cts;
private static readonly object _locker = new();
// [ObservableProperty]
// private string[] _strategyList;
// [ObservableProperty]
// private string[] _strategyList;
[ObservableProperty]
private bool _switchAutoGeniusInvokationEnabled;
@@ -83,13 +83,19 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw
[ObservableProperty]
private string _switchAutoTrackPathButtonText = "启动";
[ObservableProperty]
private bool _switchAutoMusicGameEnabled;
[ObservableProperty]
private string _switchAutoMusicGameButtonText = "启动";
[ObservableProperty]
private bool _switchAutoAlbumEnabled;
[ObservableProperty]
private string _switchAutoAlbumButtonText = "启动";
[ObservableProperty]
private List<string> _domainNameList;
@@ -110,8 +116,7 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw
//_combatStrategyList = ["根据队伍自动选择", .. LoadCustomScript(Global.Absolute(@"User\AutoFight"))];
_domainNameList = MapLazyAssets.Instance.DomainNameList;
_autoFightViewModel=new AutoFightViewModel(Config);
_autoFightViewModel = new AutoFightViewModel(Config);
}
[RelayCommand]
@@ -264,7 +269,7 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw
[RelayCommand]
public void OnOpenFightFolder()
{
_autoFightViewModel?.OnOpenFightFolder();
_autoFightViewModel?.OnOpenFightFolder();
}
[Obsolete]
@@ -351,7 +356,16 @@ public partial class TaskSettingsPageViewModel : ObservableObject, INavigationAw
{
await Launcher.LaunchUriAsync(new Uri("https://bgi.huiyadan.com/feats/task/music.html"));
}
[RelayCommand]
public async Task OnSwitchAutoAlbum()
{
SwitchAutoAlbumEnabled = true;
await new TaskRunner(DispatcherTimerOperationEnum.UseSelfCaptureImage)
.RunSoloTaskAsync(new AutoAlbumTask(new AutoMusicGameParam()));
SwitchAutoAlbumEnabled = false;
}
[RelayCommand]
public void OnOpenLocalScriptRepo()
{