Skip to content

Commit 9284a51

Browse files
committed
自动秘境支持指定树脂刷取次数 #1440 #1116 #692 #426
1 parent 269869e commit 9284a51

File tree

7 files changed

+307
-71
lines changed

7 files changed

+307
-71
lines changed

BetterGenshinImpact/GameTask/AutoDomain/AutoDomainConfig.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CommunityToolkit.Mvvm.ComponentModel;
22
using System;
3+
using System.Collections.Generic;
34

45
namespace BetterGenshinImpact.GameTask.AutoDomain;
56

@@ -51,4 +52,32 @@ public partial class AutoDomainConfig : ObservableObject
5152
// 周日奖励序号
5253
[ObservableProperty]
5354
private string _sundaySelectedValue = string.Empty;
55+
56+
// 指定树脂的使用次数
57+
[ObservableProperty]
58+
private bool _specifyResinUse = false;
59+
60+
// 自定义使用树脂优先级
61+
[ObservableProperty]
62+
private List<string> _resinPriorityList =
63+
[
64+
"浓缩树脂",
65+
"原粹树脂"
66+
];
67+
68+
// 使用原粹树脂刷取副本次数
69+
[ObservableProperty]
70+
private int _originalResinUseCount = 0;
71+
72+
//使用浓缩树脂刷取副本次数
73+
[ObservableProperty]
74+
private int _condensedResinUseCount = 0;
75+
76+
// 使用须臾树脂刷取副本次数
77+
[ObservableProperty]
78+
private int _transientResinUseCount = 0;
79+
80+
// 使用脆弱树脂刷取副本次数
81+
[ObservableProperty]
82+
private int _fragileResinUseCount = 0;
5483
}

BetterGenshinImpact/GameTask/AutoDomain/AutoDomainParam.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using BetterGenshinImpact.GameTask.Model;
1+
using System.Collections.Generic;
2+
using BetterGenshinImpact.GameTask.Model;
23
using System.Threading;
34

45
namespace BetterGenshinImpact.GameTask.AutoDomain;
@@ -25,6 +26,27 @@ public class AutoDomainParam : BaseTaskParam
2526
// 1~4
2627
public string MaxArtifactStar { get; set; } = "4";
2728

29+
public bool SpecifyResinUse { get; set; } = false;
30+
31+
// 使用树脂优先级
32+
public List<string> ResinPriorityList { get; set; } =
33+
[
34+
"浓缩树脂",
35+
"原粹树脂"
36+
];
37+
38+
// 使用原粹树脂刷取副本次数
39+
public int OriginalResinUseCount { get; set; } = 0;
40+
41+
// 使用浓缩树脂刷取副本次数
42+
public int CondensedResinUseCount { get; set; } = 0;
43+
44+
// 使用须臾树脂刷取副本次数
45+
public int TransientResinUseCount { get; set; } = 0;
46+
47+
// 使用脆弱树脂刷取副本次数
48+
public int FragileResinUseCount { get; set; } = 0;
49+
2850
public AutoDomainParam(int domainRoundNum, string path)
2951
{
3052
DomainRoundNum = domainRoundNum;
@@ -45,5 +67,11 @@ public void SetDefault()
4567
SundaySelectedValue = config.SundaySelectedValue;
4668
AutoArtifactSalvage = config.AutoArtifactSalvage;
4769
MaxArtifactStar = TaskContext.Instance().Config.AutoArtifactSalvageConfig.MaxArtifactStar;
70+
ResinPriorityList = config.ResinPriorityList;
71+
OriginalResinUseCount = config.OriginalResinUseCount;
72+
CondensedResinUseCount = config.CondensedResinUseCount;
73+
TransientResinUseCount = config.TransientResinUseCount;
74+
FragileResinUseCount = config.FragileResinUseCount;
75+
SpecifyResinUse = config.SpecifyResinUse;
4876
}
4977
}

BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public class AutoDomainTask : ISoloTask
7171
private readonly string matchingChallengeString;
7272
private readonly string rapidformationString;
7373

74+
private List<ResinUseRecord> _resinPriorityListWhenSpecifyUse;
75+
7476
public AutoDomainTask(AutoDomainParam taskParam)
7577
{
7678
AutoFightAssets.DestroyInstance();
@@ -81,6 +83,8 @@ public AutoDomainTask(AutoDomainParam taskParam)
8183

8284
_combatScriptBag = CombatScriptParser.ReadAndParse(_taskParam.CombatStrategyPath);
8385

86+
_resinPriorityListWhenSpecifyUse = ResinUseRecord.BuildFromDomainParam(taskParam);
87+
8488
IStringLocalizer<AutoDomainTask> stringLocalizer =
8589
App.GetService<IStringLocalizer<AutoDomainTask>>() ?? throw new NullReferenceException();
8690
CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
@@ -184,17 +188,9 @@ private async Task DoDomain()
184188

185189
// 5. 快速领取奖励并判断是否有下一轮
186190
Logger.LogInformation("自动秘境:{Text}", "5. 领取奖励");
187-
if (!await GettingTreasure(i == _taskParam.DomainRoundNum - 1))
191+
if (!await GettingTreasure())
188192
{
189-
if (i == _taskParam.DomainRoundNum - 1)
190-
{
191-
Logger.LogInformation("配置的{Cnt}轮秘境已经完成,结束自动秘境", _taskParam.DomainRoundNum);
192-
}
193-
else
194-
{
195-
Logger.LogInformation("体力已经耗尽,结束自动秘境");
196-
}
197-
193+
Logger.LogInformation("体力耗尽或者设置轮次已达标,结束自动秘境");
198194
break;
199195
}
200196

@@ -1011,14 +1007,13 @@ private Task LockCameraToEastTask(CancellationTokenSource cts, Task moveAvatarTa
10111007
/// <summary>
10121008
/// 领取奖励
10131009
/// </summary>
1014-
/// <param name="isLastTurn">是否最后一轮</param>
1015-
private async Task<bool> GettingTreasure(bool isLastTurn)
1010+
private async Task<bool> GettingTreasure()
10161011
{
1012+
bool isLastTurn = false;
10171013
// 等待窗口弹出
10181014
await Delay(300, _ct);
10191015

1020-
// OCR 弹出框
1021-
var noOriginalResin = false;
1016+
// 1. OCR 直到确认弹出框弹出
10221017
bool chooseResinPrompt = await NewRetry.WaitForAction(() =>
10231018
{
10241019
using var ra = CaptureToRectArea();
@@ -1028,48 +1023,77 @@ private async Task<bool> GettingTreasure(bool isLastTurn)
10281023
{
10291024
// 解决水龙王按下左键后没松开,然后后续点击按下就没反应了,界面上点一下
10301025
// res.Click();
1031-
noOriginalResin = regionList.Any(t => t.Text.Contains("数量不足") || t.Text.Contains("补充原粹树脂"));
10321026
return true;
10331027
}
10341028
return false;
10351029
}, _ct, 10, 500);
10361030
Debug.WriteLine("识别到选择树脂页");
10371031
await Delay(800, _ct);
10381032

1039-
if (noOriginalResin)
1033+
// 再 OCR 一次,弹出框,确认当前是否有原粹树脂
1034+
using var ra2 = CaptureToRectArea();
1035+
var textListInPrompt = ra2.FindMulti(RecognitionObject.Ocr(ra2.Width * 0.25, ra2.Height * 0.2, ra2.Width * 0.5, ra2.Height * 0.6));
1036+
if (textListInPrompt.Any(t => t.Text.Contains("数量不足") || t.Text.Contains("补充")))
10401037
{
10411038
// 没有原粹树脂,直接退出秘境
10421039
Logger.LogInformation("自动秘境:原粹树脂已用尽,退出秘境");
1043-
Simulation.SendInput.Keyboard.KeyPress(VK.VK_ESCAPE);
1044-
await Delay(500, _ct);
1045-
Simulation.SendInput.Keyboard.KeyPress(VK.VK_ESCAPE);
1046-
await Delay(800, _ct);
1047-
Bv.ClickBlackConfirmButton(CaptureToRectArea());
1040+
await ExitDomain();
10481041
return false;
10491042
}
10501043

1051-
// 如果没有选择树脂的提示,说明只有原粹树脂
1052-
ResinStatus? resinStatus = null;
10531044
if (chooseResinPrompt)
10541045
{
1046+
using var ra3 = CaptureToRectArea();
10551047

1056-
// 弹出框
1057-
using var ra2 = CaptureToRectArea();
1058-
// 识别树脂状况
1059-
resinStatus = ResinStatus.RecogniseFromRegion(ra2);
1060-
resinStatus.Print(Logger);
1061-
1062-
if (resinStatus.CondensedResinCount > 0)
1048+
if (!_taskParam.SpecifyResinUse)
10631049
{
1064-
PressUseResin(ra2, "浓缩树脂");
1065-
resinStatus.CondensedResinCount -= 1;
1050+
// 识别树脂状况
1051+
var resinStatus = ResinStatus.RecogniseFromRegion(ra3);
1052+
resinStatus.Print(Logger);
1053+
1054+
if (resinStatus.CondensedResinCount > 0)
1055+
{
1056+
PressUseResin(ra3, "浓缩树脂");
1057+
resinStatus.CondensedResinCount -= 1;
1058+
}
1059+
else if (resinStatus.OriginalResinCount >= 20)
1060+
{
1061+
PressUseResin(ra3, "原粹树脂");
1062+
resinStatus.OriginalResinCount -= 20;
1063+
}
1064+
1065+
if (resinStatus is { CondensedResinCount: <= 0, OriginalResinCount: < 20 })
1066+
{
1067+
// 没树脂了就是最后一回合了
1068+
isLastTurn = true;
1069+
}
10661070
}
1067-
else if (resinStatus.OriginalResinCount >= 20)
1071+
else
10681072
{
1069-
PressUseResin(ra2, "原粹树脂");
1070-
resinStatus.OriginalResinCount -= 20;
1073+
var textListInPrompt2 = ra3.FindMulti(RecognitionObject.Ocr(ra3.Width * 0.25, ra3.Height * 0.2, ra3.Width * 0.5, ra3.Height * 0.6));
1074+
// 按优先级使用
1075+
foreach (var record in _resinPriorityListWhenSpecifyUse)
1076+
{
1077+
if (record.RemainCount > 0 && PressUseResin(textListInPrompt2, record.Name))
1078+
{
1079+
record.RemainCount -= 1;
1080+
Logger.LogInformation("自动秘境:{Name} 刷取 {Re}/{Max}", record.Name, record.MaxCount - record.RemainCount, record.MaxCount);
1081+
break;
1082+
}
1083+
}
1084+
1085+
if (_resinPriorityListWhenSpecifyUse.Sum(o => o.RemainCount) <= 0)
1086+
{
1087+
// 全部刷完
1088+
isLastTurn = true;
1089+
}
10711090
}
10721091
}
1092+
else
1093+
{
1094+
// 如果没有选择树脂的提示,说明只有原粹树脂
1095+
// 继续向下执行
1096+
}
10731097

10741098
Sleep(1000, _ct);
10751099

@@ -1090,30 +1114,15 @@ private async Task<bool> GettingTreasure(bool isLastTurn)
10901114
return false;
10911115
}
10921116
}
1093-
1094-
if (resinStatus != null)
1117+
else
10951118
{
1096-
// 前面识别了体力的时候
1097-
if (resinStatus.CondensedResinCount <= 0 && resinStatus.OriginalResinCount < 20)
1098-
{
1099-
// 没有体力了退出
1100-
var exitRectArea = ra.Find(AutoFightAssets.Instance.ExitRa);
1101-
if (!exitRectArea.IsEmpty())
1102-
{
1103-
exitRectArea.Click();
1104-
return false;
1105-
}
1106-
}
1107-
else
1119+
if (!chooseResinPrompt)
11081120
{
1109-
// 有体力继续
1110-
confirmRectArea.Click();
1111-
return true;
1121+
// TODO 前面没有弹框的情况下,意味着只有原粹树脂,要再识别一次右上角确认树脂余量,没有余量直接退出
11121122
}
1113-
}
1114-
else
1115-
{
1116-
// 前面没有弹框的情况下,意味着只有原粹树脂,要再识别一次右上角确认树脂余量
1123+
// 有体力继续
1124+
confirmRectArea.Click();
1125+
return true;
11171126
}
11181127
}
11191128

@@ -1123,9 +1132,23 @@ private async Task<bool> GettingTreasure(bool isLastTurn)
11231132
throw new NormalEndException("未检测到秘境结束,可能是背包物品已满。");
11241133
}
11251134

1135+
private async Task ExitDomain()
1136+
{
1137+
Simulation.SendInput.Keyboard.KeyPress(VK.VK_ESCAPE);
1138+
await Delay(500, _ct);
1139+
Simulation.SendInput.Keyboard.KeyPress(VK.VK_ESCAPE);
1140+
await Delay(800, _ct);
1141+
Bv.ClickBlackConfirmButton(CaptureToRectArea());
1142+
}
1143+
11261144
private bool PressUseResin(ImageRegion ra, string resinName)
11271145
{
11281146
var regionList = ra.FindMulti(RecognitionObject.Ocr(ra.Width * 0.25, ra.Height * 0.2, ra.Width * 0.5, ra.Height * 0.6));
1147+
return PressUseResin(regionList, resinName);
1148+
}
1149+
1150+
private bool PressUseResin(List<Region> regionList, string resinName)
1151+
{
11291152
var resinKey = regionList.FirstOrDefault(t => t.Text.Contains(resinName));
11301153
if (resinKey != null)
11311154
{
@@ -1134,7 +1157,8 @@ private bool PressUseResin(ImageRegion ra, string resinName)
11341157
if (useList.Count != 0)
11351158
{
11361159
// 找到使用按键
1137-
var useKey = useList.FirstOrDefault(t => t.X > ra.Width / 2 && IsHeightOverlap(t, resinKey));
1160+
var useKey = useList.FirstOrDefault(t => t.X > TaskContext.Instance().SystemInfo.CaptureAreaRect.Width / 2
1161+
&& IsHeightOverlap(t, resinKey));
11381162
if (useKey != null)
11391163
{
11401164
// 点击使用
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace BetterGenshinImpact.GameTask.AutoDomain.Model;
5+
6+
/// <summary>
7+
/// 树脂使用记录
8+
/// 用于自动秘境指定树脂刷取次数时候,计算剩余刷取次数
9+
/// </summary>
10+
public class ResinUseRecord
11+
{
12+
public string Name { get; set; }
13+
14+
public int RemainCount { get; set; }
15+
16+
public int MaxCount { get; set; }
17+
18+
public ResinUseRecord(string name, int maxCount)
19+
{
20+
Name = name;
21+
RemainCount = maxCount;
22+
MaxCount = maxCount;
23+
}
24+
25+
public static List<ResinUseRecord> BuildFromDomainParam(AutoDomainParam taskParam)
26+
{
27+
List<ResinUseRecord> list = [];
28+
if (taskParam.SpecifyResinUse)
29+
{
30+
if (taskParam.CondensedResinUseCount > 0)
31+
{
32+
list.Add(new ResinUseRecord("浓缩树脂", taskParam.CondensedResinUseCount));
33+
}
34+
if (taskParam.OriginalResinUseCount > 0)
35+
{
36+
list.Add(new ResinUseRecord("原粹树脂", taskParam.OriginalResinUseCount));
37+
}
38+
if (taskParam.TransientResinUseCount > 0)
39+
{
40+
list.Add(new ResinUseRecord("须臾树脂", taskParam.TransientResinUseCount));
41+
}
42+
if (taskParam.FragileResinUseCount > 0)
43+
{
44+
list.Add(new ResinUseRecord("脆弱树脂", taskParam.FragileResinUseCount));
45+
}
46+
47+
if (list.Count == 0)
48+
{
49+
throw new Exception("你选择了指定树脂刷取次数,请至少配置一种树脂的刷取次数!");
50+
}
51+
}
52+
53+
return list;
54+
}
55+
}

BetterGenshinImpact/View/Pages/OneDragonFlowPage.xaml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -335,11 +335,16 @@
335335

336336

337337
<!-- 自动秘境 -->
338-
<TextBlock Margin="4,0,0,4"
339-
FontSize="14"
340-
Foreground="{DynamicResource SystemAccentColorPrimaryBrush}"
341-
Text="自动秘境" />
342-
338+
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Margin="4,0,0,4">
339+
<TextBlock FontSize="14"
340+
Foreground="{DynamicResource SystemAccentColorPrimaryBrush}"
341+
Text="自动秘境" />
342+
<TextBlock Margin="4,0,0,0"
343+
VerticalAlignment="Center"
344+
FontSize="11"
345+
Text="(此处未覆盖的配置可在 独立任务-自动秘境 中配置)" />
346+
</StackPanel>
347+
343348

344349
<ui:CardExpander Margin="0,0,0,12" ContentPadding="0">
345350
<ui:CardExpander.Icon>

0 commit comments

Comments
 (0)