mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
Feat/multi lan (#1336)
* 记录一次对hutaofisher的访谈,帮助开发者理解其算法
* 本地化HelloWorld
* .csproj取消windows版本号,此处导致了IDE在新建代码文件和自动生成代码时,默认命名空间丢失的问题。已知VisualStudio和ReSharper存在这个问题。
* 优化扩展方法写法,改为从localizer扩展;Converter优化写法,避免冲突;新增两种语言,待测试ocr效果
* Revert ".csproj取消windows版本号,此处导致了IDE在新建代码文件和自动生成代码时,默认命名空间丢失的问题。已知VisualStudio和ReSharper存在这个问题。"
This reverts commit 8bd7ee74c5.
* localizer改为由构造函数传入以支持单元测试;一个英语上钩的单元测试
* 传送任务支持英语游戏界面;本地化参数挪至OtherConfig类下,但界面位置暂不挪动,待定
* 调整resx位置风格,放在直接使用字符串的类下;一条龙合成树脂及领取每日奖励支持游戏内中英双语
* 删除无用碎片文件
* 删去两个不必要的Sdcb包引用
* Paddle服务类去掉分类模型;检测和识别新增支持繁中和法语,配有单元测试;因小语种识别效果不理想,使用正则匹配替换多处识别文本相等或包含判断;钓鱼、一条龙合成树脂及领取每日奖励支持游戏内繁中和法语;
* 检查今日奖励任务的多语言化;右侧联机的P图标检测区域宽度缩减,避免英语角色名被误识别成P
* AutoDomainTask的游戏多语言化,由于我的游戏账号无法测试,仅配一些测试用例
* 修复有3个Mizuki导致异常的bug,临时用拼音代替新角色英文名,并为该数据初始化方法添加单元测试
* 瓦雷莎删去别名“牛牛”,因荒泷一斗已占用此别名;别名加载和读取优化
* 加个锁避免单元测试中多线程初始化paddle崩溃
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -22,7 +23,9 @@ using BetterGenshinImpact.GameTask.Common.Job;
|
||||
using BetterGenshinImpact.GameTask.Common.Map;
|
||||
using BetterGenshinImpact.GameTask.Model.Area;
|
||||
using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
|
||||
using BetterGenshinImpact.Helpers;
|
||||
using BetterGenshinImpact.Helpers.Extensions;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenCvSharp;
|
||||
using Vanara.PInvoke;
|
||||
@@ -48,7 +51,7 @@ public class TpTask(CancellationToken ct)
|
||||
/// 直接通过缩放比例按钮计算缩小按钮的Y坐标
|
||||
/// </summary>
|
||||
private readonly int _zoomOutButtonY = TaskContext.Instance().Config.TpConfig.ZoomEndY + 24; // y-coordinate for zoom-out button = _zoomEndY + 24
|
||||
|
||||
|
||||
private const double DisplayTpPointZoomLevel = 4.4; // 传送点显示的时候的地图比例
|
||||
|
||||
/// <summary>
|
||||
@@ -57,7 +60,7 @@ public class TpTask(CancellationToken ct)
|
||||
public async Task TpToStatueOfTheSeven()
|
||||
{
|
||||
await CheckInBigMapUi();
|
||||
|
||||
|
||||
// 提前调整至恰当的缩放以更快的传送
|
||||
if (_tpConfig.MapZoomEnabled)
|
||||
{
|
||||
@@ -103,7 +106,7 @@ public class TpTask(CancellationToken ct)
|
||||
await new PathExecutor(ct).MoveTo(waypointForTrack);
|
||||
Simulation.SendInput.SimulateAction(GIActions.Drop);
|
||||
}
|
||||
|
||||
|
||||
await Delay((int)(_tpConfig.HpRestoreDuration * 1000), ct);
|
||||
}
|
||||
|
||||
@@ -153,9 +156,9 @@ public class TpTask(CancellationToken ct)
|
||||
}
|
||||
}
|
||||
// 获取最近的神像位置
|
||||
return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像");;
|
||||
return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过大地图传送到指定坐标最近的传送点,然后移动到指定坐标
|
||||
/// </summary>
|
||||
@@ -275,7 +278,7 @@ public class TpTask(CancellationToken ct)
|
||||
|
||||
Logger.LogWarning("传送等待超时,换台电脑吧");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 传送点是否在大地图窗口内
|
||||
/// </summary>
|
||||
@@ -423,13 +426,13 @@ public class TpTask(CancellationToken ct)
|
||||
++exceptionTimes;
|
||||
mapCenterPoint = new Point2f(0f, 0f); // 其他恰当的初始值?
|
||||
}
|
||||
|
||||
|
||||
var (xOffset, yOffset) = (x - mapCenterPoint.X, y - mapCenterPoint.Y);
|
||||
double totalMoveMouseX = _tpConfig.MapScaleFactor * Math.Abs(xOffset) / currentZoomLevel;
|
||||
double totalMoveMouseY = _tpConfig.MapScaleFactor * Math.Abs(yOffset) / currentZoomLevel;
|
||||
double mouseDistance = Math.Sqrt(totalMoveMouseX * totalMoveMouseX + totalMoveMouseY * totalMoveMouseY);
|
||||
// 缩小地图到恰当的缩放
|
||||
if (_tpConfig.MapZoomEnabled)
|
||||
if (_tpConfig.MapZoomEnabled)
|
||||
{
|
||||
if (mouseDistance > _tpConfig.MapZoomOutDistance)
|
||||
{
|
||||
@@ -443,7 +446,7 @@ public class TpTask(CancellationToken ct)
|
||||
currentZoomLevel = nextZoomLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 开始移动并放大地图
|
||||
for (var iteration = 0; iteration < _tpConfig.MaxIterations; iteration++)
|
||||
{
|
||||
@@ -476,7 +479,7 @@ public class TpTask(CancellationToken ct)
|
||||
int moveMouseY = (int)Math.Min(totalMoveMouseY, _tpConfig.MaxMouseMove * totalMoveMouseY / mouseDistance) * Math.Sign(yOffset);
|
||||
double moveMouseLength = Math.Sqrt(moveMouseX * moveMouseX + moveMouseY * moveMouseY);
|
||||
int moveSteps = Math.Max((int)moveMouseLength / 10, 3); // 每次移动的步数最小为 3,避免除 0 错误
|
||||
|
||||
|
||||
await MouseMoveMap(moveMouseX, moveMouseY, moveSteps);
|
||||
try
|
||||
{
|
||||
@@ -526,7 +529,7 @@ public class TpTask(CancellationToken ct)
|
||||
/// 调整地图缩放级别以加速移动
|
||||
/// </summary>
|
||||
/// <param name="zoomIn">是否放大地图</param>
|
||||
[Obsolete]
|
||||
[Obsolete]
|
||||
private async Task AdjustMapZoomLevel(bool zoomIn)
|
||||
{
|
||||
if (zoomIn)
|
||||
@@ -598,33 +601,37 @@ public class TpTask(CancellationToken ct)
|
||||
Simulation.SendInput.Mouse.LeftButtonUp();
|
||||
}
|
||||
|
||||
private int[] GenerateSteps(int delta, int steps) {
|
||||
private int[] GenerateSteps(int delta, int steps)
|
||||
{
|
||||
double[] factors = new double[steps];
|
||||
double sum = 0;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
factors[i] = Math.Cos(i * Math.PI / (2 * steps));
|
||||
sum += factors[i];
|
||||
}
|
||||
|
||||
int[] stepsArr = new int[steps];
|
||||
int remaining = delta;
|
||||
|
||||
|
||||
// 两阶段分配:基础值 + 余数补偿
|
||||
for (int i = 0; i < steps; i++) {
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
double ratio = factors[i] / sum;
|
||||
stepsArr[i] = (int)(delta * ratio); // 基础值
|
||||
remaining -= stepsArr[i];
|
||||
}
|
||||
|
||||
int center = steps / 2;
|
||||
for (int r = 0; r < Math.Abs(remaining); r++) {
|
||||
for (int r = 0; r < Math.Abs(remaining); r++)
|
||||
{
|
||||
int target = (center + r) % steps; // 从中点开始螺旋分配
|
||||
stepsArr[target] += remaining > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return stepsArr;
|
||||
}
|
||||
|
||||
|
||||
public Point2f GetPositionFromBigMap()
|
||||
{
|
||||
return GetBigMapCenterPoint();
|
||||
@@ -796,14 +803,26 @@ public class TpTask(CancellationToken ct)
|
||||
|
||||
GameCaptureRegion.GameRegionClick((rect, scale) => (rect.Width - 160 * scale, rect.Height - 60 * scale));
|
||||
await Delay(300, ct);
|
||||
var ra = CaptureToRectArea();
|
||||
using var ra = CaptureToRectArea();
|
||||
var list = ra.FindMulti(new RecognitionObject
|
||||
{
|
||||
RecognitionType = RecognitionTypes.Ocr,
|
||||
RegionOfInterest = new Rect(ra.Width / 2, 0, ra.Width / 2, ra.Height)
|
||||
});
|
||||
list.FirstOrDefault(r => r.Text.Length == minCountry.Length && !r.Text.Contains("委托") && r.Text.Contains(minCountry))?.Click();
|
||||
Logger.LogInformation("切换到区域:{Country}", minCountry);
|
||||
IStringLocalizer<MapLazyAssets> stringLocalizer = App.GetService<IStringLocalizer<MapLazyAssets>>() ?? throw new NullReferenceException(nameof(stringLocalizer));
|
||||
CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
|
||||
string minCountryLocalized = stringLocalizer.WithCultureGet(cultureInfo, minCountry);
|
||||
string commissionLocalized = stringLocalizer.WithCultureGet(cultureInfo, "委托");
|
||||
Region? matchRect = list.FirstOrDefault(r => r.Text.Length == minCountryLocalized.Length && !r.Text.Contains(commissionLocalized) && r.Text.Contains(minCountryLocalized));
|
||||
if (matchRect == null)
|
||||
{
|
||||
Logger.LogWarning("切换区域失败:{Country}", minCountry);
|
||||
}
|
||||
else
|
||||
{
|
||||
matchRect.Click();
|
||||
Logger.LogInformation("切换到区域:{Country}", minCountry);
|
||||
}
|
||||
await Delay(500, ct);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user