mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
avatar & weapon level slider
This commit is contained in:
@@ -12,6 +12,7 @@ using Snap.Hutao.Service.Navigation;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Principal;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace Snap.Hutao.Core.LifeCycle;
|
||||
|
||||
@@ -53,11 +54,6 @@ internal static class Activation
|
||||
/// <returns>是否提升了权限</returns>
|
||||
public static bool GetElevated()
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
|
||||
{
|
||||
WindowsPrincipal principal = new(identity);
|
||||
@@ -65,6 +61,19 @@ internal static class Activation
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以管理员模式重启
|
||||
/// </summary>
|
||||
/// <returns>任务</returns>
|
||||
public static async ValueTask RestartAsElevatedAsync()
|
||||
{
|
||||
if (GetElevated())
|
||||
{
|
||||
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 响应激活事件
|
||||
/// 激活事件一般不会在UI线程上触发
|
||||
|
||||
@@ -192,11 +192,6 @@ internal sealed class ExtendedWindow<TWindow> : IRecipient<BackdropTypeChangedMe
|
||||
// 48 is the navigation button leftInset
|
||||
RectInt32 dragRect = StructMarshal.RectInt32(new(48, 0), titleBar.ActualSize).Scale(scale);
|
||||
appTitleBar.SetDragRectangles(dragRect.Enumerate().ToArray());
|
||||
|
||||
// workaround for https://github.com/microsoft/WindowsAppSDK/issues/2976
|
||||
SizeInt32 size = appWindow.ClientSize;
|
||||
size.Height -= (int)(31 * scale);
|
||||
appWindow.ResizeClient(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@
|
||||
<cwuc:SwitchPresenter.ContentTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition/>
|
||||
<ContentThemeTransition/>
|
||||
</TransitionCollection>
|
||||
</cwuc:SwitchPresenter.ContentTransitions>
|
||||
<cwuc:Case>
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.BaseValue;
|
||||
|
||||
/// <summary>
|
||||
/// 基础数值信息
|
||||
/// </summary>
|
||||
internal sealed class BaseValueInfo : ObservableObject
|
||||
{
|
||||
private readonly List<PropertyCurveValue> propValues;
|
||||
private readonly Dictionary<int, Dictionary<GrowCurveType, float>> growCurveMap;
|
||||
private readonly Dictionary<int, Promote>? promoteMap;
|
||||
|
||||
private int currentLevel;
|
||||
private List<NameValue<string>> values = default!;
|
||||
private bool promoted = true;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的基础数值信息
|
||||
/// </summary>
|
||||
/// <param name="maxLevel">最大等级</param>
|
||||
/// <param name="propValues">属性与初始值</param>
|
||||
/// <param name="growCurveMap">生长曲线</param>
|
||||
/// <param name="promoteMap">突破加成</param>
|
||||
public BaseValueInfo(int maxLevel, List<PropertyCurveValue> propValues, Dictionary<int, Dictionary<GrowCurveType, float>> growCurveMap, Dictionary<int, Promote>? promoteMap = null)
|
||||
{
|
||||
this.propValues = propValues;
|
||||
this.growCurveMap = growCurveMap;
|
||||
this.promoteMap = promoteMap;
|
||||
|
||||
MaxLevel = maxLevel;
|
||||
CurrentLevel = maxLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大等级
|
||||
/// </summary>
|
||||
public int MaxLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 对应的基础值
|
||||
/// </summary>
|
||||
public List<NameValue<string>> Values { get => values; set => SetProperty(ref values, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 当前等级
|
||||
/// </summary>
|
||||
public int CurrentLevel
|
||||
{
|
||||
get => currentLevel;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref currentLevel, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(CurrentLevelFormatted));
|
||||
UpdateValues(value, promoted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化当前等级
|
||||
/// </summary>
|
||||
public string CurrentLevelFormatted
|
||||
{
|
||||
get => $"Lv.{CurrentLevel}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否突破
|
||||
/// </summary>
|
||||
public bool Promoted
|
||||
{
|
||||
get => promoted;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref promoted, value))
|
||||
{
|
||||
UpdateValues(currentLevel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateValues(int level, bool promoted)
|
||||
{
|
||||
List<NameValue<string>> values = new(propValues.Count);
|
||||
|
||||
foreach (PropertyCurveValue propValue in propValues)
|
||||
{
|
||||
float value = propValue.Value * growCurveMap[level].GetValueOrDefault(propValue.Type);
|
||||
if (promoteMap != null)
|
||||
{
|
||||
int promoteLevel = GetPromoteLevel(level, promoted);
|
||||
float addValue = promoteMap[promoteLevel].AddProperties.GetValueOrDefault(propValue.Property, 0F);
|
||||
|
||||
value += addValue;
|
||||
}
|
||||
|
||||
values.Add(Metadata.Converter.PropertyDescriptor.FormatNameValue(propValue.Property, value));
|
||||
}
|
||||
|
||||
Values = values;
|
||||
}
|
||||
|
||||
private int GetPromoteLevel(int level, bool promoted)
|
||||
{
|
||||
if (MaxLevel <= 70)
|
||||
{
|
||||
if (promoted)
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
>= 60 => 4,
|
||||
>= 50 => 3,
|
||||
>= 40 => 2,
|
||||
>= 20 => 1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
> 60 => 4,
|
||||
> 50 => 3,
|
||||
> 40 => 2,
|
||||
> 20 => 1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (promoted)
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
>= 80 => 6,
|
||||
>= 70 => 5,
|
||||
>= 60 => 4,
|
||||
>= 50 => 3,
|
||||
>= 40 => 2,
|
||||
>= 20 => 1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
> 80 => 6,
|
||||
> 70 => 5,
|
||||
> 60 => 4,
|
||||
> 50 => 3,
|
||||
> 40 => 2,
|
||||
> 20 => 1,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.BaseValue;
|
||||
|
||||
/// <summary>
|
||||
/// 战斗属性与初始值
|
||||
/// </summary>
|
||||
internal sealed class PropertyCurveValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的战斗属性与初始值
|
||||
/// </summary>
|
||||
/// <param name="property">战斗属性</param>
|
||||
/// <param name="type">类型</param>
|
||||
/// <param name="value">初始值</param>
|
||||
public PropertyCurveValue(FightProperty property, GrowCurveType type, float value)
|
||||
{
|
||||
Property = property;
|
||||
Type = type;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 战斗属性值
|
||||
/// </summary>
|
||||
public FightProperty Property { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 曲线类型
|
||||
/// </summary>
|
||||
public GrowCurveType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始值
|
||||
/// </summary>
|
||||
public float Value { get; }
|
||||
}
|
||||
@@ -30,4 +30,4 @@ internal class Item : INameIcon
|
||||
/// 星级
|
||||
/// </summary>
|
||||
public ItemQuality Quality { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ internal sealed class CalculableAvatar : ObservableObject, ICalculableAvatar
|
||||
{
|
||||
AvatarId = avatar.Id;
|
||||
LevelMin = 1;
|
||||
LevelMax = int.Parse(avatar.Property.Parameters.Last().Level);
|
||||
LevelMax = 90;
|
||||
Skills = avatar.SkillDepot.EnumerateCompositeSkillsNoInherents().Select(p => p.ToCalculable()).ToList();
|
||||
Name = avatar.Name;
|
||||
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class CalculableWeapon : ObservableObject, ICalculableWeapon
|
||||
{
|
||||
WeaponId = weapon.Id;
|
||||
LevelMin = 1;
|
||||
LevelMax = int.Parse(weapon.Property.Parameters.Last().Level);
|
||||
LevelMax = (int)weapon.Quality >= 3 ? 90 : 70;
|
||||
Name = weapon.Name;
|
||||
Icon = EquipIconConverter.IconNameToUri(weapon.Icon);
|
||||
Quality = weapon.RankLevel;
|
||||
|
||||
74
src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/GrowCurveType.cs
Normal file
74
src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/GrowCurveType.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
/// <summary>
|
||||
/// 生长曲线
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[SuppressMessage("", "SA1602")]
|
||||
internal enum GrowCurveType
|
||||
{
|
||||
GROW_CURVE_NONE = 0,
|
||||
GROW_CURVE_HP = 1,
|
||||
GROW_CURVE_ATTACK = 2,
|
||||
GROW_CURVE_STAMINA = 3,
|
||||
GROW_CURVE_STRIKE = 4,
|
||||
GROW_CURVE_ANTI_STRIKE = 5,
|
||||
GROW_CURVE_ANTI_STRIKE1 = 6,
|
||||
GROW_CURVE_ANTI_STRIKE2 = 7,
|
||||
GROW_CURVE_ANTI_STRIKE3 = 8,
|
||||
GROW_CURVE_STRIKE_HURT = 9,
|
||||
GROW_CURVE_ELEMENT = 10,
|
||||
GROW_CURVE_KILL_EXP = 11,
|
||||
GROW_CURVE_DEFENSE = 12,
|
||||
GROW_CURVE_ATTACK_BOMB = 13,
|
||||
GROW_CURVE_HP_LITTLEMONSTER = 14,
|
||||
GROW_CURVE_ELEMENT_MASTERY = 15,
|
||||
GROW_CURVE_PROGRESSION = 16,
|
||||
GROW_CURVE_DEFENDING = 17,
|
||||
GROW_CURVE_MHP = 18,
|
||||
GROW_CURVE_MATK = 19,
|
||||
GROW_CURVE_TOWERATK = 20,
|
||||
GROW_CURVE_HP_S5 = 21,
|
||||
GROW_CURVE_HP_S4 = 22,
|
||||
GROW_CURVE_HP_2 = 23,
|
||||
GROW_CURVE_ATTACK_2 = 24,
|
||||
GROW_CURVE_ATTACK_S5 = 31,
|
||||
GROW_CURVE_ATTACK_S4 = 32,
|
||||
GROW_CURVE_ATTACK_S3 = 33,
|
||||
GROW_CURVE_STRIKE_S5 = 34,
|
||||
GROW_CURVE_DEFENSE_S5 = 41,
|
||||
GROW_CURVE_DEFENSE_S4 = 42,
|
||||
GROW_CURVE_ATTACK_101 = 1101,
|
||||
GROW_CURVE_ATTACK_102 = 1102,
|
||||
GROW_CURVE_ATTACK_103 = 1103,
|
||||
GROW_CURVE_ATTACK_104 = 1104,
|
||||
GROW_CURVE_ATTACK_105 = 1105,
|
||||
GROW_CURVE_ATTACK_201 = 1201,
|
||||
GROW_CURVE_ATTACK_202 = 1202,
|
||||
GROW_CURVE_ATTACK_203 = 1203,
|
||||
GROW_CURVE_ATTACK_204 = 1204,
|
||||
GROW_CURVE_ATTACK_205 = 1205,
|
||||
GROW_CURVE_ATTACK_301 = 1301,
|
||||
GROW_CURVE_ATTACK_302 = 1302,
|
||||
GROW_CURVE_ATTACK_303 = 1303,
|
||||
GROW_CURVE_ATTACK_304 = 1304,
|
||||
GROW_CURVE_ATTACK_305 = 1305,
|
||||
GROW_CURVE_CRITICAL_101 = 2101,
|
||||
GROW_CURVE_CRITICAL_102 = 2102,
|
||||
GROW_CURVE_CRITICAL_103 = 2103,
|
||||
GROW_CURVE_CRITICAL_104 = 2104,
|
||||
GROW_CURVE_CRITICAL_105 = 2105,
|
||||
GROW_CURVE_CRITICAL_201 = 2201,
|
||||
GROW_CURVE_CRITICAL_202 = 2202,
|
||||
GROW_CURVE_CRITICAL_203 = 2203,
|
||||
GROW_CURVE_CRITICAL_204 = 2204,
|
||||
GROW_CURVE_CRITICAL_205 = 2205,
|
||||
GROW_CURVE_CRITICAL_301 = 2301,
|
||||
GROW_CURVE_CRITICAL_302 = 2302,
|
||||
GROW_CURVE_CRITICAL_303 = 2303,
|
||||
GROW_CURVE_CRITICAL_304 = 2304,
|
||||
GROW_CURVE_CRITICAL_305 = 2305,
|
||||
}
|
||||
20
src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/MonsterType.cs
Normal file
20
src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/MonsterType.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
/// <summary>
|
||||
/// 怪物种类
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[SuppressMessage("", "SA1602")]
|
||||
internal enum MonsterType
|
||||
{
|
||||
MONSTER_NONE = 0,
|
||||
MONSTER_ORDINARY = 1,
|
||||
MONSTER_BOSS = 2,
|
||||
MONSTER_ENV_ANIMAL = 3,
|
||||
MONSTER_LITTLE_MONSTER = 4,
|
||||
MONSTER_FISH = 5,
|
||||
MONSTER_PARTNER = 6,
|
||||
}
|
||||
@@ -95,4 +95,4 @@ internal enum WeaponType
|
||||
/// </summary>
|
||||
[LocalizationKey("ModelIntrinsicWeaponTypePole")]
|
||||
WEAPON_POLE = 13,
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,11 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IName
|
||||
/// </summary>
|
||||
public List<Material>? CultivationItemsView { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大等级
|
||||
/// </summary>
|
||||
public int MaxLevel { get => 90; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ICalculableAvatar ToCalculable()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,11 @@ internal partial class Avatar
|
||||
/// </summary>
|
||||
public AvatarId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 突破提升 Id 外键
|
||||
/// </summary>
|
||||
public PromoteId PromoteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序号
|
||||
/// </summary>
|
||||
@@ -65,9 +70,15 @@ internal partial class Avatar
|
||||
public WeaponType Weapon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 属性
|
||||
/// 基础数值
|
||||
/// </summary>
|
||||
public PropertiesParameters Property { get; set; } = default!;
|
||||
public BaseValue BaseValue { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 生长曲线
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(Core.Json.Converter.StringEnumKeyDictionaryConverter))]
|
||||
public Dictionary<FightProperty, GrowCurveType> GrowCurves { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 技能
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Snap.Hutao.Model.Metadata;
|
||||
[SuppressMessage("", "SA1600")]
|
||||
internal static class AvatarIds
|
||||
{
|
||||
public static readonly AvatarId Kate = 10000001;
|
||||
public static readonly AvatarId Ayaka = 10000002;
|
||||
public static readonly AvatarId Qin = 10000003;
|
||||
|
||||
@@ -107,6 +106,7 @@ internal static class AvatarIds
|
||||
SideIcon = "UI_AvatarIcon_Side_PlayerBoy",
|
||||
Quality = Intrinsic.ItemQuality.QUALITY_ORANGE,
|
||||
},
|
||||
|
||||
[PlayerGirl] = new()
|
||||
{
|
||||
Name = "旅行者",
|
||||
|
||||
25
src/Snap.Hutao/Snap.Hutao/Model/Metadata/BaseValue.cs
Normal file
25
src/Snap.Hutao/Snap.Hutao/Model/Metadata/BaseValue.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata;
|
||||
|
||||
/// <summary>
|
||||
/// 基础数值
|
||||
/// </summary>
|
||||
internal class BaseValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础生命值
|
||||
/// </summary>
|
||||
public float HpBase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 基础攻击力
|
||||
/// </summary>
|
||||
public float AttackBase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 基础防御力
|
||||
/// </summary>
|
||||
public float DefenseBase { get; set; }
|
||||
}
|
||||
@@ -15,7 +15,18 @@ namespace Snap.Hutao.Model.Metadata.Converter;
|
||||
internal sealed class PropertyDescriptor : ValueConverter<PropertiesParameters, List<LevelParameters<string, ParameterDescription>>?>
|
||||
{
|
||||
/// <summary>
|
||||
/// 格式化对
|
||||
/// 格式化名称与值
|
||||
/// </summary>
|
||||
/// <param name="property">属性</param>
|
||||
/// <param name="value">值</param>
|
||||
/// <returns>对</returns>
|
||||
public static NameValue<string> FormatNameValue(FightProperty property, float value)
|
||||
{
|
||||
return new(property.GetLocalizedDescription(), FormatValue(property, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化名称与描述
|
||||
/// </summary>
|
||||
/// <param name="property">属性</param>
|
||||
/// <param name="value">值</param>
|
||||
|
||||
24
src/Snap.Hutao/Snap.Hutao/Model/Metadata/GrowCurve.cs
Normal file
24
src/Snap.Hutao/Snap.Hutao/Model/Metadata/GrowCurve.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata;
|
||||
|
||||
/// <summary>
|
||||
/// 生长曲线
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class GrowCurve
|
||||
{
|
||||
/// <summary>
|
||||
/// 等级
|
||||
/// </summary>
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 曲线 值相乘
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(Core.Json.Converter.StringEnumKeyDictionaryConverter))]
|
||||
public Dictionary<GrowCurveType, float> Curves { get; set; } = default!;
|
||||
}
|
||||
64
src/Snap.Hutao/Snap.Hutao/Model/Metadata/Monster/Monster.cs
Normal file
64
src/Snap.Hutao/Snap.Hutao/Model/Metadata/Monster/Monster.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Monster;
|
||||
|
||||
/// <summary>
|
||||
/// 敌对生物
|
||||
/// </summary>
|
||||
internal sealed class Monster
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public MonsterId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内部代号
|
||||
/// </summary>
|
||||
public string MonsterName { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
public string Title { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public string Icon { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 怪物种类
|
||||
/// </summary>
|
||||
public MonsterType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 强化标签
|
||||
/// </summary>
|
||||
public List<string>? Affixes { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 掉落物 Id
|
||||
/// </summary>
|
||||
public IEnumerable<MaterialId>? Drops { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 基本属性
|
||||
/// </summary>
|
||||
public MonsterBaseValue BaseValue { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 生长曲线
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(Core.Json.Converter.StringEnumKeyDictionaryConverter))]
|
||||
public Dictionary<FightProperty, GrowCurveType> GrowCurves { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Monster;
|
||||
|
||||
/// <summary>
|
||||
/// 怪物基本属性
|
||||
/// </summary>
|
||||
internal sealed class MonsterBaseValue : BaseValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 火抗
|
||||
/// </summary>
|
||||
public float FireSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 草抗
|
||||
/// </summary>
|
||||
public float GrassSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 水抗
|
||||
/// </summary>
|
||||
public float WaterSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 雷抗
|
||||
/// </summary>
|
||||
public float ElecSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 风抗
|
||||
/// </summary>
|
||||
public float WindSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 冰抗
|
||||
/// </summary>
|
||||
public float IceSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 岩抗
|
||||
/// </summary>
|
||||
public float RockSubHurt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物抗
|
||||
/// </summary>
|
||||
public float PhysicalSubHurt { get; set; }
|
||||
}
|
||||
30
src/Snap.Hutao/Snap.Hutao/Model/Metadata/Promote.cs
Normal file
30
src/Snap.Hutao/Snap.Hutao/Model/Metadata/Promote.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata;
|
||||
|
||||
/// <summary>
|
||||
/// 突破加成
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class Promote
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public PromoteId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 突破等级
|
||||
/// </summary>
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 增加的属性
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(Core.Json.Converter.StringEnumKeyDictionaryConverter))]
|
||||
public Dictionary<FightProperty, float> AddProperties { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Weapon;
|
||||
|
||||
/// <summary>
|
||||
/// 生长曲线与值
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class GrowCurveTypeValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
public GrowCurveType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public float Value { get; set; }
|
||||
}
|
||||
@@ -28,6 +28,11 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource
|
||||
get => RankLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大等级
|
||||
/// </summary>
|
||||
public int MaxLevel { get => ((int)Quality) >= 3 ? 90 : 70; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ICalculableWeapon ToCalculable()
|
||||
{
|
||||
|
||||
@@ -17,6 +17,11 @@ internal sealed partial class Weapon
|
||||
/// </summary>
|
||||
public WeaponId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 突破 Id
|
||||
/// </summary>
|
||||
public PromoteId PromoteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 武器类型
|
||||
/// </summary>
|
||||
@@ -48,9 +53,10 @@ internal sealed partial class Weapon
|
||||
public string AwakenIcon { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 属性
|
||||
/// 生长曲线
|
||||
/// </summary>
|
||||
public PropertiesParameters Property { get; set; } = default!;
|
||||
[JsonConverter(typeof(Core.Json.Converter.StringEnumKeyDictionaryConverter))]
|
||||
public Dictionary<FightProperty, GrowCurveTypeValue> GrowCurves { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 被动信息, 无被动的武器为 <see langword="null"/>
|
||||
|
||||
66
src/Snap.Hutao/Snap.Hutao/Model/Primitive/MonsterId.cs
Normal file
66
src/Snap.Hutao/Snap.Hutao/Model/Primitive/MonsterId.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Primitive.Converter;
|
||||
|
||||
namespace Snap.Hutao.Model.Primitive;
|
||||
|
||||
/// <summary>
|
||||
/// 8位 怪物Id
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[JsonConverter(typeof(IdentityConverter<MonsterId>))]
|
||||
internal readonly struct MonsterId : IEquatable<MonsterId>
|
||||
{
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public readonly int Value;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MonsterId"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="value">value</param>
|
||||
public MonsterId(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static implicit operator int(MonsterId value)
|
||||
{
|
||||
return value.Value;
|
||||
}
|
||||
|
||||
public static implicit operator MonsterId(int value)
|
||||
{
|
||||
return new(value);
|
||||
}
|
||||
|
||||
public static bool operator ==(MonsterId left, MonsterId right)
|
||||
{
|
||||
return left.Value == right.Value;
|
||||
}
|
||||
|
||||
public static bool operator !=(MonsterId left, MonsterId right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(MonsterId other)
|
||||
{
|
||||
return Value == other.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is MonsterId other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Value.GetHashCode();
|
||||
}
|
||||
}
|
||||
66
src/Snap.Hutao/Snap.Hutao/Model/Primitive/PromoteId.cs
Normal file
66
src/Snap.Hutao/Snap.Hutao/Model/Primitive/PromoteId.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Primitive.Converter;
|
||||
|
||||
namespace Snap.Hutao.Model.Primitive;
|
||||
|
||||
/// <summary>
|
||||
/// 1-5位 角色突破提升Id
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[JsonConverter(typeof(IdentityConverter<PromoteId>))]
|
||||
internal readonly struct PromoteId : IEquatable<PromoteId>
|
||||
{
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public readonly int Value;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PromoteId"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="value">value</param>
|
||||
public PromoteId(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static implicit operator int(PromoteId value)
|
||||
{
|
||||
return value.Value;
|
||||
}
|
||||
|
||||
public static implicit operator PromoteId(int value)
|
||||
{
|
||||
return new(value);
|
||||
}
|
||||
|
||||
public static bool operator ==(PromoteId left, PromoteId right)
|
||||
{
|
||||
return left.Value == right.Value;
|
||||
}
|
||||
|
||||
public static bool operator !=(PromoteId left, PromoteId right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(PromoteId other)
|
||||
{
|
||||
return Value == other.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is PromoteId other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Value.GetHashCode();
|
||||
}
|
||||
}
|
||||
@@ -1428,6 +1428,24 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 等级 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewControlBaseValueSliderLevel {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewControlBaseValueSliderLevel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 突破后 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewControlBaseValueSliderPromoted {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewControlBaseValueSliderPromoted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 加载中,请稍候 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -573,6 +573,12 @@
|
||||
<data name="ViewAvatarPropertyHeader" xml:space="preserve">
|
||||
<value>我的角色</value>
|
||||
</data>
|
||||
<data name="ViewControlBaseValueSliderLevel" xml:space="preserve">
|
||||
<value>等级</value>
|
||||
</data>
|
||||
<data name="ViewControlBaseValueSliderPromoted" xml:space="preserve">
|
||||
<value>突破后</value>
|
||||
</data>
|
||||
<data name="ViewControlLoadingText" xml:space="preserve">
|
||||
<value>加载中,请稍候</value>
|
||||
</data>
|
||||
|
||||
@@ -24,7 +24,6 @@ internal static class ReliquaryWeightConfiguration
|
||||
new AffixWeight(AvatarIds.Qin, 0, 75, 0, 100, 100, 0, 55, 100).Anemo().Phyiscal(),
|
||||
new AffixWeight(AvatarIds.Lisa, 0, 75, 0, 100, 100, 75, 0, 0).Electro(),
|
||||
new AffixWeight(AvatarIds.Barbara, 100, 50, 0, 50, 50, 0, 55, 100).Hydro(80),
|
||||
new AffixWeight(AvatarIds.Barbara, 50, 75, 0, 100, 100, 0, 55, 100, "暴力奶妈").Hydro(),
|
||||
new AffixWeight(AvatarIds.Kaeya, 0, 75, 0, 100, 100, 0, 30, 0).Cryo().Phyiscal(),
|
||||
new AffixWeight(AvatarIds.Diluc, 0, 75, 0, 100, 100, 75, 0, 0).Pyro(),
|
||||
new AffixWeight(AvatarIds.Razor, 0, 75, 0, 100, 100, 0, 0, 0).Electro().Phyiscal(),
|
||||
@@ -37,16 +36,13 @@ internal static class ReliquaryWeightConfiguration
|
||||
new AffixWeight(AvatarIds.Ningguang, 0, 75, 0, 100, 100, 0, 30, 0).Geo(),
|
||||
new AffixWeight(AvatarIds.Klee, 0, 75, 0, 100, 100, 75, 30, 0).Pyro(),
|
||||
new AffixWeight(AvatarIds.Zhongli, 80, 75, 0, 100, 100, 0, 55, 0).Geo().Phyiscal(50),
|
||||
new AffixWeight(AvatarIds.Zhongli, 100, 55, 0, 100, 100, 0, 55, 0, "血牛钟离").Geo(75),
|
||||
new AffixWeight(AvatarIds.Zhongli, 100, 55, 0, 100, 100, 0, 75, 0, "血牛钟离(2命+)").Geo(75),
|
||||
new AffixWeight(AvatarIds.Fischl, 0, 75, 0, 100, 100, 75, 0, 0).Electro().Phyiscal(60),
|
||||
new AffixWeight(AvatarIds.Bennett, 100, 50, 0, 100, 100, 0, 55, 100).Pyro(80),
|
||||
new AffixWeight(AvatarIds.Tartaglia, 0, 75, 0, 100, 100, 75, 30, 0).Hydro(),
|
||||
new AffixWeight(AvatarIds.Noel, 0, 50, 90, 100, 100, 0, 70, 0).Geo(),
|
||||
new AffixWeight(AvatarIds.Qiqi, 0, 75, 0, 100, 100, 0, 55, 100).Cryo().Phyiscal(),
|
||||
new AffixWeight(AvatarIds.Chongyun, 0, 75, 0, 100, 100, 75, 55, 0).Cryo(),
|
||||
new AffixWeight(AvatarIds.Ganyu, 0, 75, 0, 100, 100, 75, 0, 0, "融化流").Cryo(),
|
||||
new AffixWeight(AvatarIds.Ganyu, 0, 75, 0, 100, 100, 0, 55, 0, "永冻流").Cryo(),
|
||||
new AffixWeight(AvatarIds.Ganyu, 0, 75, 0, 100, 100, 75, 0, 0).Cryo(),
|
||||
new AffixWeight(AvatarIds.Albedo, 0, 0, 100, 100, 100, 0, 0, 0).Geo(),
|
||||
new AffixWeight(AvatarIds.Diona, 100, 50, 0, 50, 50, 0, 90, 100).Cryo(),
|
||||
new AffixWeight(AvatarIds.Mona, 0, 75, 0, 100, 100, 75, 75, 0).Hydro(),
|
||||
|
||||
@@ -72,10 +72,10 @@ internal static class GachaStatisticsExtension
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[SuppressMessage("", "IDE0057")]
|
||||
private static Color GetColorByName(string name)
|
||||
{
|
||||
Span<byte> codes = MD5.HashData(Encoding.UTF8.GetBytes(name));
|
||||
Color color = Color.FromArgb(255, codes.Slice(0, 5).Average(), codes.Slice(5, 5).Average(), codes.Slice(10, 5).Average());
|
||||
return color;
|
||||
return Color.FromArgb(255, codes.Slice(0, 5).Average(), codes.Slice(5, 5).Average(), codes.Slice(10, 5).Average());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +198,8 @@ internal sealed class GachaLogService : IGachaLogService
|
||||
.OrderBy(i => i.Id)
|
||||
.FirstOrDefault()?.Id ?? long.MaxValue;
|
||||
|
||||
logger.LogInformation("Last Id to trim with [{id}]", trimId);
|
||||
|
||||
IEnumerable<GachaItem> toAdd = list
|
||||
.OrderByDescending(i => i.Id)
|
||||
.Where(i => i.Id < trimId)
|
||||
|
||||
@@ -5,6 +5,7 @@ using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
using Snap.Hutao.Model.Metadata.Achievement;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Metadata.Monster;
|
||||
using Snap.Hutao.Model.Metadata.Reliquary;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
@@ -154,5 +155,47 @@ internal interface IMetadataService : ICastableService
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>材料列表</returns>
|
||||
ValueTask<List<Material>> GetMaterialsAsync(CancellationToken token = default(CancellationToken));
|
||||
ValueTask<List<Material>> GetMaterialsAsync(CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取怪物列表
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>怪物列表</returns>
|
||||
ValueTask<List<Monster>> GetMonstersAsync(CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取等级角色曲线映射
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>等级角色曲线映射</returns>
|
||||
ValueTask<Dictionary<int, Dictionary<GrowCurveType, float>>> GetLevelToAvatarCurveMapAsync(CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取等级怪物曲线映射
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>等级怪物曲线映射</returns>
|
||||
ValueTask<Dictionary<int, Dictionary<GrowCurveType, float>>> GetLevelToMonsterCurveMapAsync(CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取等级武器曲线映射
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>等级武器曲线映射</returns>
|
||||
ValueTask<Dictionary<int, Dictionary<GrowCurveType, float>>> GetLevelToWeaponCurveMapAsync(CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取角色突破列表
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色突破列表</returns>
|
||||
ValueTask<List<Promote>> GetAvatarPromotesAsync(CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取武器突破列表
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>武器突破列表</returns>
|
||||
ValueTask<List<Promote>> GetWeaponPromotesAsync(CancellationToken token = default(CancellationToken));
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
using Snap.Hutao.Model.Metadata.Achievement;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Metadata.Monster;
|
||||
using Snap.Hutao.Model.Metadata.Reliquary;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
|
||||
@@ -32,6 +33,18 @@ internal sealed partial class MetadataService
|
||||
return FromCacheOrFileAsync<List<Avatar>>("Avatar", token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<List<Promote>> GetAvatarPromotesAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheOrFileAsync<List<Promote>>("AvatarPromote", token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<List<Promote>> GetWeaponPromotesAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheOrFileAsync<List<Promote>>("WeaponPromote", token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<List<GachaEvent>> GetGachaEventsAsync(CancellationToken token = default)
|
||||
{
|
||||
@@ -44,6 +57,12 @@ internal sealed partial class MetadataService
|
||||
return FromCacheOrFileAsync<List<Material>>("Material", token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<List<Monster>> GetMonstersAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheOrFileAsync<List<Monster>>("Monster", token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<List<Reliquary>> GetReliquariesAsync(CancellationToken token = default)
|
||||
{
|
||||
|
||||
@@ -51,6 +51,24 @@ internal sealed partial class MetadataService
|
||||
return FromCacheAsDictionaryAsync<WeaponId, Weapon>("Weapon", w => w.Id, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<int, Dictionary<GrowCurveType, float>>> GetLevelToAvatarCurveMapAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheAsDictionaryAsync<int, Dictionary<GrowCurveType, float>, GrowCurve>("AvatarCurve", a => a.Level, a => a.Curves, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<int, Dictionary<GrowCurveType, float>>> GetLevelToMonsterCurveMapAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheAsDictionaryAsync<int, Dictionary<GrowCurveType, float>, GrowCurve>("MonsterCurve", m => m.Level, m => m.Curves, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<int, Dictionary<GrowCurveType, float>>> GetLevelToWeaponCurveMapAsync(CancellationToken token = default)
|
||||
{
|
||||
return FromCacheAsDictionaryAsync<int, Dictionary<GrowCurveType, float>, GrowCurve>("WeaponCurve", w => w.Level, w => w.Curves, token);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<Dictionary<string, Avatar>> GetNameToAvatarMapAsync(CancellationToken token = default)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using Snap.Hutao.Core.Diagnostics;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
@@ -29,6 +30,7 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
||||
private readonly JsonSerializerOptions options;
|
||||
private readonly ILogger<MetadataService> logger;
|
||||
private readonly IMemoryCache memoryCache;
|
||||
private readonly string locale;
|
||||
|
||||
/// <summary>
|
||||
/// 用于指示初始化是否完成
|
||||
@@ -58,7 +60,8 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
||||
this.memoryCache = memoryCache;
|
||||
httpClient = httpClientFactory.CreateClient(nameof(MetadataService));
|
||||
|
||||
metadataFolderPath = Path.Combine(Core.CoreEnvironment.DataFolder, "Metadata");
|
||||
locale = GetTextMapLocale();
|
||||
metadataFolderPath = Path.Combine(Core.CoreEnvironment.DataFolder, "Metadata", locale);
|
||||
Directory.CreateDirectory(metadataFolderPath);
|
||||
}
|
||||
|
||||
@@ -86,6 +89,41 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
||||
logger.LogInformation("Metadata initializaion completed in {time}ms", stopwatch.GetElapsedTime().TotalMilliseconds);
|
||||
}
|
||||
|
||||
private static string GetTextMapLocale()
|
||||
{
|
||||
CultureInfo cultureInfo = CultureInfo.CurrentCulture;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (cultureInfo == CultureInfo.InvariantCulture)
|
||||
{
|
||||
// Fallback to Chinese.
|
||||
return "CHS";
|
||||
}
|
||||
|
||||
switch (cultureInfo.Name)
|
||||
{
|
||||
case "de": return "DE"; // German
|
||||
case "en": return "EN"; // English
|
||||
case "es": return "ES"; // Spanish
|
||||
case "fr": return "FR"; // French
|
||||
case "id": return "ID"; // Indonesian
|
||||
case "it": return "IT"; // Italian
|
||||
case "ja": return "JP"; // Japanese
|
||||
case "kr": return "JP"; // Japanese
|
||||
case "ko": return "KR"; // Korean
|
||||
case "pt": return "PT"; // Portuguese
|
||||
case "ru": return "RU"; // Russian
|
||||
case "th": return "TH"; // Thai
|
||||
case "tr": return "TR"; // Turkish
|
||||
case "vi": return "TR"; // Vietnamese
|
||||
case "zh-CHS": return "CHS"; // Chinese (Simplified) Legacy
|
||||
case "zh-CHT": return "CHT"; // Chinese (Traditional) Legacy
|
||||
default: cultureInfo = cultureInfo.Parent; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> TryUpdateMetadataAsync(CancellationToken token)
|
||||
{
|
||||
IDictionary<string, string>? metaMd5Map;
|
||||
@@ -93,7 +131,7 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
||||
{
|
||||
// download meta check file
|
||||
metaMd5Map = await httpClient
|
||||
.GetFromJsonAsync<IDictionary<string, string>>(Web.HutaoEndpoints.HutaoMetadataFile(MetaFileName), options, token)
|
||||
.GetFromJsonAsync<IDictionary<string, string>>(Web.HutaoEndpoints.HutaoMetadataFile(locale, MetaFileName), options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (metaMd5Map is null)
|
||||
@@ -162,7 +200,7 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
||||
private async Task DownloadMetadataAsync(string fileFullName, CancellationToken token)
|
||||
{
|
||||
Stream sourceStream = await httpClient
|
||||
.GetStreamAsync(Web.HutaoEndpoints.HutaoMetadataFile(fileFullName), token)
|
||||
.GetStreamAsync(Web.HutaoEndpoints.HutaoMetadataFile(locale, fileFullName), token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Write stream while convert LF to CRLF
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<None Remove="Resource\Segoe Fluent Icons.ttf" />
|
||||
<None Remove="Resource\WelcomeView_Background.png" />
|
||||
<None Remove="stylecop.json" />
|
||||
<None Remove="View\Control\BaseValueSlider.xaml" />
|
||||
<None Remove="View\Control\BottomTextControl.xaml" />
|
||||
<None Remove="View\Control\DescParamComboBox.xaml" />
|
||||
<None Remove="View\Control\ItemIcon.xaml" />
|
||||
@@ -178,7 +179,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.230118.102" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.230217.4" />
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.435">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -442,4 +443,9 @@
|
||||
<LastGenOutput>SH.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="View\Control\BaseValueSlider.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
57
src/Snap.Hutao/Snap.Hutao/View/Control/BaseValueSlider.xaml
Normal file
57
src/Snap.Hutao/Snap.Hutao/View/Control/BaseValueSlider.xaml
Normal file
@@ -0,0 +1,57 @@
|
||||
<UserControl
|
||||
x:Class="Snap.Hutao.View.Control.BaseValueSlider"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel>
|
||||
<wsc:SettingsGroup Margin="0,-64,0,0" VerticalAlignment="Top">
|
||||
<wsc:Setting Padding="12,0,6,0" Header="{shcm:ResourceString Name=ViewControlBaseValueSliderLevel}">
|
||||
<wsc:Setting.ActionContent>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="8,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind BaseValueInfo.CurrentLevelFormatted, Mode=OneWay}"/>
|
||||
<CheckBox
|
||||
MinWidth="0"
|
||||
Margin="16,0,8,0"
|
||||
Padding="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{shcm:ResourceString Name=ViewControlBaseValueSliderPromoted}"
|
||||
IsChecked="{x:Bind BaseValueInfo.Promoted, Mode=TwoWay}"/>
|
||||
<Slider
|
||||
MinWidth="240"
|
||||
Margin="16,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Maximum="{x:Bind BaseValueInfo.MaxLevel, Mode=OneWay}"
|
||||
Minimum="1"
|
||||
StepFrequency="1"
|
||||
Value="{x:Bind BaseValueInfo.CurrentLevel, Mode=TwoWay}"/>
|
||||
|
||||
</StackPanel>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
</wsc:SettingsGroup>
|
||||
|
||||
<ItemsControl VerticalAlignment="Top" ItemsSource="{x:Bind BaseValueInfo.Values, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<wsc:Setting
|
||||
Margin="0,2,0,0"
|
||||
Padding="12,0"
|
||||
Header="{Binding Name}">
|
||||
<wsc:Setting.ActionContent>
|
||||
<TextBlock Text="{Binding Value}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Model.Binding.BaseValue;
|
||||
|
||||
namespace Snap.Hutao.View.Control;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
internal sealed partial class BaseValueSlider : UserControl
|
||||
{
|
||||
private static readonly DependencyProperty BaseValueInfoProperty = Property<BaseValueSlider>.Depend<BaseValueInfo>(nameof(BaseValueInfo));
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µĻ<C2B5><C4BB><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public BaseValueSlider()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>Ϣ
|
||||
/// </summary>
|
||||
public BaseValueInfo BaseValueInfo
|
||||
{
|
||||
get => (BaseValueInfo)GetValue(BaseValueInfoProperty);
|
||||
set => SetValue(BaseValueInfoProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -289,13 +289,11 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<!-- 属性 -->
|
||||
<ContentControl
|
||||
<shvc:BaseValueSlider
|
||||
Margin="16,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Content="{Binding Selected.Property, Mode=OneWay}"
|
||||
ContentTemplate="{StaticResource PropertyDataTemplate}"/>
|
||||
|
||||
BaseValueInfo="{Binding BaseValueInfo, Mode=OneWay}"/>
|
||||
<TextBlock
|
||||
Margin="16,32,0,0"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
|
||||
@@ -190,12 +190,11 @@
|
||||
Margin="16,16,0,0"
|
||||
Text="{Binding Selected.Description}"
|
||||
TextWrapping="Wrap"/>
|
||||
<ContentControl
|
||||
<shvc:BaseValueSlider
|
||||
Margin="16,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Content="{Binding Selected.Property, Mode=OneWay}"
|
||||
ContentTemplate="{StaticResource PropertyDataTemplate}"/>
|
||||
BaseValueInfo="{Binding BaseValueInfo, Mode=OneWay}"/>
|
||||
<TextBlock
|
||||
Margin="16,32,0,0"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
|
||||
@@ -184,7 +184,7 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
||||
if (SetProperty(ref selectedCulture, value))
|
||||
{
|
||||
SettingEntry entry = appDbContext.Settings.SingleOrAdd(SettingEntry.Culture, CultureInfo.CurrentCulture.Name);
|
||||
entry.Value = selectedCulture.Value;
|
||||
entry.Value = selectedCulture?.Value;
|
||||
appDbContext.Settings.UpdateAndSave(entry);
|
||||
AppInstance.Restart(string.Empty);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Snap.Hutao.Model.Binding.BaseValue;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Intrinsic.Immutable;
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
@@ -42,6 +44,9 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
private AdvancedCollectionView? avatars;
|
||||
private Avatar? selected;
|
||||
private string? filterText;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<int, Dictionary<GrowCurveType, float>>? levelAvatarCurveMap;
|
||||
private List<Promote>? promotes;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的角色资料视图模型
|
||||
@@ -66,7 +71,21 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 选中的角色
|
||||
/// </summary>
|
||||
public Avatar? Selected { get => selected; set => SetProperty(ref selected, value); }
|
||||
public Avatar? Selected
|
||||
{
|
||||
get => selected; set
|
||||
{
|
||||
if (SetProperty(ref selected, value))
|
||||
{
|
||||
UpdateBaseValueInfo(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基础数值信息
|
||||
/// </summary>
|
||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选文本
|
||||
@@ -92,6 +111,9 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
levelAvatarCurveMap = await metadataService.GetLevelToAvatarCurveMapAsync().ConfigureAwait(false);
|
||||
promotes = await metadataService.GetAvatarPromotesAsync().ConfigureAwait(false);
|
||||
|
||||
Dictionary<MaterialId, Material> idMaterialMap = await metadataService.GetIdToMaterialMapAsync().ConfigureAwait(false);
|
||||
List<Avatar> avatars = await metadataService.GetAvatarsAsync().ConfigureAwait(false);
|
||||
List<Avatar> sorted = avatars
|
||||
@@ -179,6 +201,30 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBaseValueInfo(Avatar? avatar)
|
||||
{
|
||||
if (avatar == null)
|
||||
{
|
||||
BaseValueInfo = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary<int, Promote> avatarPromoteMap = promotes!.Where(p => p.Id == avatar.PromoteId).ToDictionary(p => p.Level);
|
||||
|
||||
FightProperty promoteProperty = avatarPromoteMap[0].AddProperties.Keys.Last();
|
||||
|
||||
List<PropertyCurveValue> propertyCurveValues = new()
|
||||
{
|
||||
new(FightProperty.FIGHT_PROP_BASE_HP, avatar.GrowCurves[FightProperty.FIGHT_PROP_BASE_HP], avatar.BaseValue.HpBase),
|
||||
new(FightProperty.FIGHT_PROP_BASE_ATTACK, avatar.GrowCurves[FightProperty.FIGHT_PROP_BASE_ATTACK], avatar.BaseValue.AttackBase),
|
||||
new(FightProperty.FIGHT_PROP_BASE_DEFENSE, avatar.GrowCurves[FightProperty.FIGHT_PROP_BASE_DEFENSE], avatar.BaseValue.DefenseBase),
|
||||
new(promoteProperty, GrowCurveType.GROW_CURVE_NONE, 0),
|
||||
};
|
||||
|
||||
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap!, avatarPromoteMap);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFilter(string? input)
|
||||
{
|
||||
if (Avatars != null)
|
||||
|
||||
@@ -5,9 +5,12 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Snap.Hutao.Model.Binding.BaseValue;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Intrinsic.Immutable;
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
@@ -44,6 +47,9 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
private AdvancedCollectionView? weapons;
|
||||
private Weapon? selected;
|
||||
private string? filterText;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<int, Dictionary<GrowCurveType, float>>? levelWeaponCurveMap;
|
||||
private List<Promote>? promotes;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的武器资料视图模型
|
||||
@@ -68,7 +74,21 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 选中的角色
|
||||
/// </summary>
|
||||
public Weapon? Selected { get => selected; set => SetProperty(ref selected, value); }
|
||||
public Weapon? Selected
|
||||
{
|
||||
get => selected; set
|
||||
{
|
||||
if (SetProperty(ref selected, value))
|
||||
{
|
||||
UpdateBaseValueInfo(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基础数值信息
|
||||
/// </summary>
|
||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选文本
|
||||
@@ -94,6 +114,9 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
levelWeaponCurveMap = await metadataService.GetLevelToWeaponCurveMapAsync().ConfigureAwait(false);
|
||||
promotes = await metadataService.GetWeaponPromotesAsync().ConfigureAwait(false);
|
||||
|
||||
List<Weapon> weapons = await metadataService.GetWeaponsAsync().ConfigureAwait(false);
|
||||
List<Weapon> sorted = weapons
|
||||
.Where(weapon => !skippedWeapons.Contains(weapon.Id))
|
||||
@@ -175,6 +198,24 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBaseValueInfo(Weapon? weapon)
|
||||
{
|
||||
if (weapon == null)
|
||||
{
|
||||
BaseValueInfo = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary<int, Promote> weaponPromoteMap = promotes!.Where(p => p.Id == weapon.PromoteId).ToDictionary(p => p.Level);
|
||||
|
||||
List<PropertyCurveValue> propertyCurveValues = weapon.GrowCurves
|
||||
.Select(curveInfo => new PropertyCurveValue(curveInfo.Key, curveInfo.Value.Type, curveInfo.Value.Value))
|
||||
.ToList();
|
||||
|
||||
BaseValueInfo = new(weapon.MaxLevel, propertyCurveValues, levelWeaponCurveMap!, weaponPromoteMap);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFilter(string? input)
|
||||
{
|
||||
if (Weapons != null)
|
||||
@@ -237,7 +278,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
|
||||
if (intrinsics.FightProperties.Contains(value))
|
||||
{
|
||||
matches.Add(weapon.Property.Properties.ElementAtOrDefault(1).GetLocalizedDescriptionOrDefault() == value);
|
||||
matches.Add(weapon.GrowCurves.ElementAtOrDefault(1).Key.GetLocalizedDescriptionOrDefault() == value);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,11 +89,12 @@ internal static class HutaoEndpoints
|
||||
/// <summary>
|
||||
/// 胡桃元数据文件
|
||||
/// </summary>
|
||||
/// <param name="locale">语言</param>
|
||||
/// <param name="fileName">文件名称</param>
|
||||
/// <returns>路径</returns>
|
||||
public static string HutaoMetadataFile(string fileName)
|
||||
public static string HutaoMetadataFile(string locale, string fileName)
|
||||
{
|
||||
return $"{HutaoMetadataSnapGenshinApi}/{fileName}";
|
||||
return $"{HutaoMetadataSnapGenshinApi}/{locale}/{fileName}";
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -144,7 +145,12 @@ internal static class HutaoEndpoints
|
||||
}
|
||||
#endregion
|
||||
|
||||
#if DEBUG
|
||||
private const string HutaoMetadataSnapGenshinApi = "http://hutao-metadata-pages.snapgenshin.cn";
|
||||
#else
|
||||
private const string HutaoMetadataSnapGenshinApi = "http://hutao-metadata.snapgenshin.com";
|
||||
#endif
|
||||
|
||||
private const string HomaSnapGenshinApi = "https://homa.snapgenshin.com";
|
||||
private const string PatcherDGPStudioApi = "https://patcher.dgp-studio.cn";
|
||||
private const string StaticSnapGenshinApi = "https://static.snapgenshin.com";
|
||||
|
||||
@@ -17,7 +17,7 @@ internal static class MemoryExtension
|
||||
/// </summary>
|
||||
/// <param name="char256">目标字符数组</param>
|
||||
/// <returns>结果字符串</returns>
|
||||
public static unsafe string AsString(this ref __CHAR_256 char256)
|
||||
public static unsafe string AsString(this in __CHAR_256 char256)
|
||||
{
|
||||
fixed (CHAR* pszModule = &char256._0)
|
||||
{
|
||||
|
||||
@@ -4,12 +4,7 @@
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
|
||||
Reference in New Issue
Block a user