From 2c0b32ab8b1b68a2c9bfec2e82c71d2579d971f8 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Tue, 20 Dec 2022 15:11:05 +0800 Subject: [PATCH] achievement progress --- .../Control/{Image => Media}/Bgra8.cs | 2 +- .../Snap.Hutao/Control/Media/Rgba8.cs | 175 ++++++++++++++++++ .../Control/Media/SoftwareBitmapExtension.cs | 42 +++++ .../Control/Text/DescriptionTextBlock.cs | 147 +-------------- .../Snap.Hutao/Core/CoreEnvironment.cs | 2 + .../Core/Database/DbSetExtension.cs | 16 +- ...hedulerHelper.cs => ScheduleTaskHelper.cs} | 2 +- .../DispatherQueueSwitchOperation.cs | 5 +- .../Snap.Hutao/Core/WebView2Helper.cs | 6 +- ...dowExtensions.cs => AppWindowExtension.cs} | 2 +- .../Core/Windowing/ExtendedWindow.cs | 3 +- .../Binding/{ => Achievement}/Achievement.cs | 2 +- .../Binding/Achievement/AchievementGoal.cs | 68 +++++++ .../Model/Binding/AvatarProperty/Avatar.cs | 31 +++- .../Model/Binding/AvatarProperty/Skill.cs | 17 +- .../Model/Binding/AvatarProperty/Weapon.cs | 22 ++- .../Avatar => Calculable}/CalculableAvatar.cs | 23 ++- .../Avatar => Calculable}/CalculableSkill.cs | 21 ++- .../Weapon => Calculable}/CalculableWeapon.cs | 22 ++- .../Model/Intrinsic/ImmutableIntrinsics.cs | 38 ++++ .../Snap.Hutao/Model/Intrinsic/WeaponType.cs | 2 +- .../Metadata/Achievement/AchievementGoal.cs | 2 +- .../Metadata/Avatar/Avatar.Implementation.cs | 1 + .../Avatar/ProudableSkill.Implementation.cs | 1 + .../Snap.Hutao/Model/Metadata/AvatarIds.cs | 2 + .../Converter/AchievementIconConverter.cs | 12 +- .../Converter/ElementNameIconConverter.cs | 2 +- .../Metadata/Weapon/Weapon.Implementation.cs | 1 + src/Snap.Hutao/Snap.Hutao/NativeMethods.txt | 2 + .../Snap.Hutao/Package.appxmanifest | 2 +- src/Snap.Hutao/Snap.Hutao/Program.cs | 4 +- .../Service/Achievement/AchievementService.cs | 2 +- .../Achievement/IAchievementService.cs | 2 +- .../Service/AvatarInfo/Factory/AffixWeight.cs | 132 +++++++++++-- .../Factory/ReliquaryWeightConfiguration.cs | 127 +++++++------ .../Factory/SummaryAvatarFactory.cs | 44 ++--- .../AvatarInfo/Factory/SummaryFactory.cs | 24 +-- .../Factory/SummaryFactoryImplementation.cs | 44 +---- .../AvatarInfo/Factory/SummaryHelper.cs | 3 +- .../Factory/SummaryMetadataContext.cs | 31 ++++ .../Factory/SummaryReliquaryFactory.cs | 42 ++--- .../Service/Cultivation/CultivationService.cs | 9 +- .../Cultivation/ICultivationService.cs | 4 +- .../Service/DailyNote/DailyNoteNotifier.cs | 48 ++--- .../Service/DailyNote/DailyNoteService.cs | 9 +- .../View/Control/DescParamComboBox.xaml.cs | 2 +- .../Snap.Hutao/View/Page/AchievementPage.xaml | 41 ++-- .../View/Page/AvatarPropertyPage.xaml | 31 +--- .../Snap.Hutao/View/Page/CultivationPage.xaml | 2 +- .../Snap.Hutao/View/Page/GachaLogPage.xaml | 6 +- .../Snap.Hutao/View/Page/SettingPage.xaml | 14 ++ .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 18 ++ .../ViewModel/AchievementViewModel.cs | 106 +++++++---- .../ViewModel/AvatarPropertyViewModel.cs | 94 +++++++--- .../ViewModel/DailyNoteViewModel.cs | 4 +- .../ExperimentalFeaturesViewModel.cs | 24 ++- .../Snap.Hutao/ViewModel/SettingViewModel.cs | 9 + .../ViewModel/WikiAvatarViewModel.cs | 13 +- .../ViewModel/WikiWeaponViewModel.cs | 79 ++++++++ .../Annotation/IgnoreSetCookieAttribute.cs | 12 -- .../Web/Hoyolab/Bbs/User/UserClient.cs | 1 - 61 files changed, 1118 insertions(+), 536 deletions(-) rename src/Snap.Hutao/Snap.Hutao/Control/{Image => Media}/Bgra8.cs (97%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Media/Rgba8.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs rename src/Snap.Hutao/Snap.Hutao/Core/{TaskSchedulerHelper.cs => ScheduleTaskHelper.cs} (98%) rename src/Snap.Hutao/Snap.Hutao/Core/Windowing/{AppWindowExtensions.cs => AppWindowExtension.cs} (94%) rename src/Snap.Hutao/Snap.Hutao/Model/Binding/{ => Achievement}/Achievement.cs (97%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Binding/Achievement/AchievementGoal.cs rename src/Snap.Hutao/Snap.Hutao/Model/{Metadata/Avatar => Calculable}/CalculableAvatar.cs (72%) rename src/Snap.Hutao/Snap.Hutao/Model/{Metadata/Avatar => Calculable}/CalculableSkill.cs (72%) rename src/Snap.Hutao/Snap.Hutao/Model/{Metadata/Weapon => Calculable}/CalculableWeapon.cs (72%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ImmutableIntrinsics.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryMetadataContext.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Annotation/IgnoreSetCookieAttribute.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/Bgra8.cs b/src/Snap.Hutao/Snap.Hutao/Control/Media/Bgra8.cs similarity index 97% rename from src/Snap.Hutao/Snap.Hutao/Control/Image/Bgra8.cs rename to src/Snap.Hutao/Snap.Hutao/Control/Media/Bgra8.cs index d993ae39..da772d90 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/Bgra8.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Media/Bgra8.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; using Windows.UI; -namespace Snap.Hutao.Control.Image; +namespace Snap.Hutao.Control.Media; /// /// BGRA8 结构 diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Media/Rgba8.cs b/src/Snap.Hutao/Snap.Hutao/Control/Media/Rgba8.cs new file mode 100644 index 00000000..3507c455 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Media/Rgba8.cs @@ -0,0 +1,175 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. +// Some part of this file came from: +// https://github.com/xunkong/desktop/tree/main/src/Desktop/Desktop/Pages/CharacterInfoPage.xaml.cs + +using CommunityToolkit.WinUI; +using System.Runtime.InteropServices; +using Windows.UI; + +namespace Snap.Hutao.Control.Media; + +/// +/// RGBA 颜色 +/// +[StructLayout(LayoutKind.Explicit)] +public struct Rgba8 +{ + /// + /// R + /// + [FieldOffset(3)] + public byte R; + + /// + /// G + /// + [FieldOffset(2)] + public byte G; + + /// + /// B + /// + [FieldOffset(1)] + public byte B; + + /// + /// A + /// + [FieldOffset(0)] + public byte A; + + [FieldOffset(0)] + private readonly uint data; + + /// + /// 构造一个新的 RGBA8 颜色 + /// + /// 色值字符串 + public Rgba8(ReadOnlySpan hex) + { + Must.Argument(hex.Length == 8, "色值长度不为8"); + R = 0; + G = 0; + B = 0; + A = 0; + data = Convert.ToUInt32(hex.ToString(), 16); + } + + private Rgba8(byte r, byte g, byte b, byte a) + { + data = 0; + R = r; + G = g; + B = b; + A = a; + } + + public static implicit operator Color(Rgba8 hexColor) + { + return Color.FromArgb(hexColor.A, hexColor.R, hexColor.G, hexColor.B); + } + + /// + /// 从 HSL 颜色转换 + /// + /// HSL 颜色 + /// RGBA8颜色 + public static Rgba8 FromHsl(HslColor hsl) + { + double chroma = (1 - Math.Abs((2 * hsl.L) - 1)) * hsl.S; + double h1 = hsl.H / 60; + double x = chroma * (1 - Math.Abs((h1 % 2) - 1)); + double m = hsl.L - (0.5 * chroma); + double r1, g1, b1; + + if (h1 < 1) + { + r1 = chroma; + g1 = x; + b1 = 0; + } + else if (h1 < 2) + { + r1 = x; + g1 = chroma; + b1 = 0; + } + else if (h1 < 3) + { + r1 = 0; + g1 = chroma; + b1 = x; + } + else if (h1 < 4) + { + r1 = 0; + g1 = x; + b1 = chroma; + } + else if (h1 < 5) + { + r1 = x; + g1 = 0; + b1 = chroma; + } + else + { + r1 = chroma; + g1 = 0; + b1 = x; + } + + byte r = (byte)(255 * (r1 + m)); + byte g = (byte)(255 * (g1 + m)); + byte b = (byte)(255 * (b1 + m)); + byte a = (byte)(255 * hsl.A); + + return new(r, g, b, a); + } + + /// + /// 转换到 HSL 颜色 + /// + /// HSL 颜色 + public HslColor ToHsl() + { + const double toDouble = 1.0 / 255; + double r = toDouble * R; + double g = toDouble * G; + double b = toDouble * B; + double max = Math.Max(Math.Max(r, g), b); + double min = Math.Min(Math.Min(r, g), b); + double chroma = max - min; + double h1; + + if (chroma == 0) + { + h1 = 0; + } + else if (max == r) + { + // The % operator doesn't do proper modulo on negative + // numbers, so we'll add 6 before using it + h1 = (((g - b) / chroma) + 6) % 6; + } + else if (max == g) + { + h1 = 2 + ((b - r) / chroma); + } + else + { + h1 = 4 + ((r - g) / chroma); + } + + double lightness = 0.5 * (max + min); + double saturation = chroma == 0 ? 0 : chroma / (1 - Math.Abs((2 * lightness) - 1)); + + HslColor ret; + ret.H = 60 * h1; + ret.S = saturation; + ret.L = lightness; + ret.A = toDouble * A; + return ret; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs new file mode 100644 index 00000000..3c5e02c8 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs @@ -0,0 +1,42 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Windows.Foundation; +using Windows.Graphics.Imaging; +using Windows.Win32; +using Windows.Win32.System.WinRT; +using WinRT; + +namespace Snap.Hutao.Control.Media; + +/// +/// 软件位图拓展 +/// +public static class SoftwareBitmapExtension +{ + /// + /// 混合模式 正常 + /// + /// 软件位图 + /// 底色 + public static unsafe void NormalBlend(this SoftwareBitmap softwareBitmap, Bgra8 tint) + { + using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) + { + using (IMemoryBufferReference reference = buffer.CreateReference()) + { + reference.As().GetBuffer(out byte* data, out uint length); + + for (int i = 0; i < length; i += 4) + { + Bgra8* pixel = (Bgra8*)(data + i); + byte baseAlpha = pixel->A; + pixel->B = (byte)(((pixel->B * baseAlpha) + (tint.B * (0xFF - baseAlpha))) / 0xFF); + pixel->G = (byte)(((pixel->G * baseAlpha) + (tint.G * (0xFF - baseAlpha))) / 0xFF); + pixel->R = (byte)(((pixel->R * baseAlpha) + (tint.R * (0xFF - baseAlpha))) / 0xFF); + pixel->A = 0xFF; + } + } + } + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Text/DescriptionTextBlock.cs b/src/Snap.Hutao/Snap.Hutao/Control/Text/DescriptionTextBlock.cs index 8cb68e12..ea1e0ffe 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Text/DescriptionTextBlock.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Text/DescriptionTextBlock.cs @@ -8,8 +8,8 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Documents; using Microsoft.UI.Xaml.Media; +using Snap.Hutao.Control.Media; using Snap.Hutao.Core; -using System.Runtime.InteropServices; using Windows.UI; namespace Snap.Hutao.Control.Text; @@ -19,8 +19,7 @@ namespace Snap.Hutao.Control.Text; /// public class DescriptionTextBlock : ContentControl { - private static readonly DependencyProperty DescriptionProperty = - Property.Depend(nameof(Description), string.Empty, OnDescriptionChanged); + private static readonly DependencyProperty DescriptionProperty = Property.Depend(nameof(Description), string.Empty, OnDescriptionChanged); private static readonly int ColorTagFullLength = "".Length; private static readonly int ColorTagLeftLength = "".Length; @@ -79,7 +78,7 @@ public class DescriptionTextBlock : ContentControl else if (description[i] == '<' && description[i + 1] == 'c') { AppendText(text, description[last..i]); - HexColor color = new(description.Slice(i + 8, 8)); + Rgba8 color = new(description.Slice(i + 8, 8)); int length = description[(i + ColorTagLeftLength)..].IndexOf('<'); AppendColorText(text, description.Slice(i + ColorTagLeftLength, length), color); @@ -115,7 +114,7 @@ public class DescriptionTextBlock : ContentControl text.Inlines.Add(new Run { Text = slice.ToString() }); } - private static void AppendColorText(TextBlock text, ReadOnlySpan slice, HexColor color) + private static void AppendColorText(TextBlock text, ReadOnlySpan slice, Rgba8 color) { Color targetColor; if (ThemeHelper.IsDarkMode(text.ActualTheme)) @@ -126,7 +125,7 @@ public class DescriptionTextBlock : ContentControl { HslColor hsl = color.ToHsl(); hsl.L *= 0.3; - targetColor = HexColor.FromHsl(hsl); + targetColor = Rgba8.FromHsl(hsl); } text.Inlines.Add(new Run @@ -154,138 +153,4 @@ public class DescriptionTextBlock : ContentControl { ApplyDescription((TextBlock)Content, Description); } - - [StructLayout(LayoutKind.Explicit)] - private struct HexColor - { - [FieldOffset(3)] - public byte R; - [FieldOffset(2)] - public byte G; - [FieldOffset(1)] - public byte B; - [FieldOffset(0)] - public byte A; - - [FieldOffset(0)] - private readonly uint data; - - public HexColor(ReadOnlySpan hex) - { - Must.Argument(hex.Length == 8, "色值长度不为8"); - R = 0; - G = 0; - B = 0; - A = 0; - data = Convert.ToUInt32(hex.ToString(), 16); - } - - private HexColor(byte r, byte g, byte b, byte a) - { - data = 0; - R = r; - G = g; - B = b; - A = a; - } - - public static implicit operator Color(HexColor hexColor) - { - return Color.FromArgb(hexColor.A, hexColor.R, hexColor.G, hexColor.B); - } - - public static HexColor FromHsl(HslColor hsl) - { - double chroma = (1 - Math.Abs((2 * hsl.L) - 1)) * hsl.S; - double h1 = hsl.H / 60; - double x = chroma * (1 - Math.Abs((h1 % 2) - 1)); - double m = hsl.L - (0.5 * chroma); - double r1, g1, b1; - - if (h1 < 1) - { - r1 = chroma; - g1 = x; - b1 = 0; - } - else if (h1 < 2) - { - r1 = x; - g1 = chroma; - b1 = 0; - } - else if (h1 < 3) - { - r1 = 0; - g1 = chroma; - b1 = x; - } - else if (h1 < 4) - { - r1 = 0; - g1 = x; - b1 = chroma; - } - else if (h1 < 5) - { - r1 = x; - g1 = 0; - b1 = chroma; - } - else - { - r1 = chroma; - g1 = 0; - b1 = x; - } - - byte r = (byte)(255 * (r1 + m)); - byte g = (byte)(255 * (g1 + m)); - byte b = (byte)(255 * (b1 + m)); - byte a = (byte)(255 * hsl.A); - - return new(r, g, b, a); - } - - public HslColor ToHsl() - { - const double toDouble = 1.0 / 255; - double r = toDouble * R; - double g = toDouble * G; - double b = toDouble * B; - double max = Math.Max(Math.Max(r, g), b); - double min = Math.Min(Math.Min(r, g), b); - double chroma = max - min; - double h1; - - if (chroma == 0) - { - h1 = 0; - } - else if (max == r) - { - // The % operator doesn't do proper modulo on negative - // numbers, so we'll add 6 before using it - h1 = (((g - b) / chroma) + 6) % 6; - } - else if (max == g) - { - h1 = 2 + ((b - r) / chroma); - } - else - { - h1 = 4 + ((r - g) / chroma); - } - - double lightness = 0.5 * (max + min); - double saturation = chroma == 0 ? 0 : chroma / (1 - Math.Abs((2 * lightness) - 1)); - - HslColor ret; - ret.H = 60 * h1; - ret.S = saturation; - ret.L = lightness; - ret.A = toDouble * A; - return ret; - } - } -} +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs index 5cb2a538..50552ce4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs @@ -5,8 +5,10 @@ using Microsoft.Win32; using Snap.Hutao.Core.Convert; using Snap.Hutao.Core.Json; using Snap.Hutao.Extension; +using System.Runtime.InteropServices; using System.Text.Json.Serialization.Metadata; using Windows.ApplicationModel; +using Windows.Win32.Foundation; namespace Snap.Hutao.Core; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Database/DbSetExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Database/DbSetExtension.cs index e3eb44af..707c50dc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Database/DbSetExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Database/DbSetExtension.cs @@ -44,11 +44,11 @@ public static class DbSetExtension /// 数据库集 /// 实体 /// 影响条数 - public static Task AddAndSaveAsync(this DbSet dbSet, TEntity entity) + public static async ValueTask AddAndSaveAsync(this DbSet dbSet, TEntity entity) where TEntity : class { dbSet.Add(entity); - return dbSet.Context().SaveChangesAsync(); + return await dbSet.Context().SaveChangesAsync().ConfigureAwait(false); } /// @@ -72,11 +72,11 @@ public static class DbSetExtension /// 数据库集 /// 实体 /// 影响条数 - public static Task AddRangeAndSaveAsync(this DbSet dbSet, IEnumerable entities) + public static async ValueTask AddRangeAndSaveAsync(this DbSet dbSet, IEnumerable entities) where TEntity : class { dbSet.AddRange(entities); - return dbSet.Context().SaveChangesAsync(); + return await dbSet.Context().SaveChangesAsync().ConfigureAwait(false); } /// @@ -100,11 +100,11 @@ public static class DbSetExtension /// 数据库集 /// 实体 /// 影响条数 - public static Task RemoveAndSaveAsync(this DbSet dbSet, TEntity entity) + public static async ValueTask RemoveAndSaveAsync(this DbSet dbSet, TEntity entity) where TEntity : class { dbSet.Remove(entity); - return dbSet.Context().SaveChangesAsync(); + return await dbSet.Context().SaveChangesAsync().ConfigureAwait(false); } /// @@ -128,10 +128,10 @@ public static class DbSetExtension /// 数据库集 /// 实体 /// 影响条数 - public static Task UpdateAndSaveAsync(this DbSet dbSet, TEntity entity) + public static async ValueTask UpdateAndSaveAsync(this DbSet dbSet, TEntity entity) where TEntity : class { dbSet.Update(entity); - return dbSet.Context().SaveChangesAsync(); + return await dbSet.Context().SaveChangesAsync().ConfigureAwait(false); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/TaskSchedulerHelper.cs b/src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs similarity index 98% rename from src/Snap.Hutao/Snap.Hutao/Core/TaskSchedulerHelper.cs rename to src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs index e7526ac1..7c460e34 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/TaskSchedulerHelper.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs @@ -10,7 +10,7 @@ namespace Snap.Hutao.Core; /// /// 任务计划器服务 /// -internal static class TaskSchedulerHelper +internal static class ScheduleTaskHelper { private const string DailyNoteRefreshTaskName = "SnapHutaoDailyNoteRefreshTask"; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatherQueueSwitchOperation.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatherQueueSwitchOperation.cs index 933c68fb..7fdc04ed 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatherQueueSwitchOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatherQueueSwitchOperation.cs @@ -43,6 +43,9 @@ public readonly struct DispatherQueueSwitchOperation : IAwaitable public void OnCompleted(Action continuation) { - dispatherQueue.TryEnqueue(() => { continuation(); }); + dispatherQueue.TryEnqueue(() => + { + continuation(); + }); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/WebView2Helper.cs b/src/Snap.Hutao/Snap.Hutao/Core/WebView2Helper.cs index 48c5acfe..1b192f5f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/WebView2Helper.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/WebView2Helper.cs @@ -50,6 +50,10 @@ internal abstract class WebView2Helper /// public static string Version { - get => version; + get + { + _ = IsSupported; + return version; + } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/AppWindowExtensions.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/AppWindowExtension.cs similarity index 94% rename from src/Snap.Hutao/Snap.Hutao/Core/Windowing/AppWindowExtensions.cs rename to src/Snap.Hutao/Snap.Hutao/Core/Windowing/AppWindowExtension.cs index 027fee31..f540d473 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/AppWindowExtensions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/AppWindowExtension.cs @@ -10,7 +10,7 @@ namespace Snap.Hutao.Core.Windowing; /// /// 扩展 /// -public static class AppWindowExtensions +public static class AppWindowExtension { /// /// 获取当前 的呈现矩形 diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs index 63b3cf11..597cc831 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs @@ -134,7 +134,8 @@ internal sealed class ExtendedWindow : IRecipient /// 用于视图绑定的成就 diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Binding/Achievement/AchievementGoal.cs b/src/Snap.Hutao/Snap.Hutao/Model/Binding/Achievement/AchievementGoal.cs new file mode 100644 index 00000000..06134b9b --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Binding/Achievement/AchievementGoal.cs @@ -0,0 +1,68 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Snap.Hutao.Model.Binding.Achievement; + +/// +/// 绑定成就分类 +/// +public class AchievementGoal : ObservableObject +{ + private double finishPercent; + private string? finishDescription; + + /// + /// 构造一个新的成就分类 + /// + /// 分类 + public AchievementGoal(Metadata.Achievement.AchievementGoal goal) + { + Id = goal.Id; + Order = goal.Order; + Name = goal.Name; + Icon = Metadata.Converter.AchievementIconConverter.IconNameToUri(goal.Icon); + } + + /// + /// Id + /// + public int Id { get; set; } + + /// + /// 排序顺序 + /// + public int Order { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } = default!; + + /// + /// 图标 + /// + public Uri? Icon { get; set; } + + /// + /// 完成百分比 + /// + public double FinishPercent { get => finishPercent; set => SetProperty(ref finishPercent, value); } + + /// + /// 完成百分比 + /// + public string? FinishDescription { get => finishDescription; set => SetProperty(ref finishDescription, value); } + + /// + /// 更新进度 + /// + /// 完成项 + /// 总项 + public void UpdateFinishPercent(int finished, int count) + { + FinishPercent = (double)finished / count; + FinishDescription = $"{finished}/{count} - {FinishPercent:P2}"; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Avatar.cs b/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Avatar.cs index 7b4406cc..e4518053 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Avatar.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Avatar.cs @@ -1,14 +1,17 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Primitive; +using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; namespace Snap.Hutao.Model.Binding.AvatarProperty; /// /// 角色信息 /// -public class Avatar +public class Avatar : ICalculableSource { /// /// 名称 @@ -45,11 +48,6 @@ public class Avatar /// public string Level { get; set; } = default!; - /// - /// 好感度等级 - /// - public int FetterLevel { get; set; } - /// /// 武器 /// @@ -84,4 +82,25 @@ public class Avatar /// 双爆评分 /// public string CritScore { get; set; } = default!; + + /// + /// 好感度等级 + /// + public int FetterLevel { get; set; } + + /// + /// Id + /// + internal AvatarId Id { get; set; } + + /// + /// 等级数字 + /// + internal int LevelNumber { get; set; } + + /// + public ICalculableAvatar ToCalculable() + { + return new CalculableAvatar(this); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Skill.cs b/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Skill.cs index cd5e9510..8bf76de3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Skill.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Skill.cs @@ -1,22 +1,35 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Metadata; +using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; namespace Snap.Hutao.Model.Binding.AvatarProperty; /// /// 天赋 /// -public class Skill : NameIconDescription +public class Skill : NameIconDescription, ICalculableSource { /// /// 技能属性 /// public LevelParam Info { get; set; } = default!; + /// + /// 技能组Id + /// + internal int GroupId { get; set; } + /// /// 技能等级,仅用于养成计算 /// - internal int Level { get; set; } + internal int LevelNumber { get; set; } + + /// + public ICalculableSkill ToCalculable() + { + return new CalculableSkill(this); + } } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Weapon.cs b/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Weapon.cs index 8079dc66..b20d8758 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Weapon.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Binding/AvatarProperty/Weapon.cs @@ -1,12 +1,16 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Calculable; +using Snap.Hutao.Model.Primitive; +using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; + namespace Snap.Hutao.Model.Binding.AvatarProperty; /// /// 武器 /// -public class Weapon : EquipBase +public class Weapon : EquipBase, ICalculableSource { /// /// 副属性 @@ -27,4 +31,20 @@ public class Weapon : EquipBase /// 精炼被动 /// public string AffixDescription { get; set; } = default!; + + /// + /// Id + /// + internal WeaponId Id { get; set; } + + /// + /// 等级数字 + /// + internal int LevelNumber { get; set; } + + /// + public ICalculableWeapon ToCalculable() + { + return new CalculableWeapon(this); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/CalculableAvatar.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs similarity index 72% rename from src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/CalculableAvatar.cs rename to src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs index edc36cb2..362afd39 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/CalculableAvatar.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs @@ -7,7 +7,7 @@ using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Model.Primitive; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; -namespace Snap.Hutao.Model.Metadata.Avatar; +namespace Snap.Hutao.Model.Calculable; /// /// 可计算角色 @@ -21,7 +21,7 @@ internal class CalculableAvatar : ObservableObject, ICalculableAvatar /// 构造一个新的可计算角色 /// /// 角色 - public CalculableAvatar(Avatar avatar) + public CalculableAvatar(Metadata.Avatar.Avatar avatar) { AvatarId = avatar.Id; LevelMin = 1; @@ -30,6 +30,25 @@ internal class CalculableAvatar : ObservableObject, ICalculableAvatar Name = avatar.Name; Icon = AvatarIconConverter.IconNameToUri(avatar.Icon); Quality = avatar.Quality; + + LevelCurrent = LevelMin; + LevelTarget = LevelMax; + } + + /// + /// 构造一个新的可计算角色 + /// + /// 角色 + public CalculableAvatar(Binding.AvatarProperty.Avatar avatar) + { + AvatarId = avatar.Id; + LevelMin = avatar.LevelNumber; + LevelMax = 90; // hard coded 90 + Skills = avatar.Skills.Select(s => s.ToCalculable()).ToList(); + Name = avatar.Name; + Icon = avatar.Icon; + Quality = avatar.Quality; + LevelCurrent = LevelMin; LevelTarget = LevelMax; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/CalculableSkill.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs similarity index 72% rename from src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/CalculableSkill.cs rename to src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs index bba49bb4..23bc7e1c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/CalculableSkill.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs @@ -3,10 +3,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Metadata.Avatar; using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; -namespace Snap.Hutao.Model.Metadata.Avatar; +namespace Snap.Hutao.Model.Calculable; /// /// 可计算的技能 @@ -28,6 +29,24 @@ internal class CalculableSkill : ObservableObject, ICalculableSkill Name = skill.Name; Icon = SkillIconConverter.IconNameToUri(skill.Icon); Quality = ItemQuality.QUALITY_NONE; + + LevelCurrent = LevelMin; + LevelTarget = LevelMax; + } + + /// + /// 构造一个新的可计算的技能 + /// + /// 技能 + public CalculableSkill(Binding.AvatarProperty.Skill skill) + { + GruopId = skill.GroupId; + LevelMin = skill.LevelNumber; + LevelMax = 10; // hard coded 10 here + Name = skill.Name; + Icon = skill.Icon; + Quality = ItemQuality.QUALITY_NONE; + LevelCurrent = LevelMin; LevelTarget = LevelMax; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/CalculableWeapon.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs similarity index 72% rename from src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/CalculableWeapon.cs rename to src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs index c0eaa0d3..67f05063 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/CalculableWeapon.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs @@ -7,7 +7,7 @@ using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Model.Primitive; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; -namespace Snap.Hutao.Model.Metadata.Weapon; +namespace Snap.Hutao.Model.Calculable; /// /// 可计算武器 @@ -21,7 +21,7 @@ public class CalculableWeapon : ObservableObject, ICalculableWeapon /// 构造一个新的可计算武器 /// /// 武器 - public CalculableWeapon(Weapon weapon) + public CalculableWeapon(Metadata.Weapon.Weapon weapon) { WeaponId = weapon.Id; LevelMin = 1; @@ -29,6 +29,24 @@ public class CalculableWeapon : ObservableObject, ICalculableWeapon Name = weapon.Name; Icon = EquipIconConverter.IconNameToUri(weapon.Icon); Quality = weapon.RankLevel; + + LevelCurrent = LevelMin; + LevelTarget = LevelMax; + } + + /// + /// 构造一个新的可计算武器 + /// + /// 武器 + public CalculableWeapon(Binding.AvatarProperty.Weapon weapon) + { + WeaponId = weapon.Id; + LevelMin = weapon.LevelNumber; + LevelMax = (int)weapon.Quality >= 3 ? 90 : 70; + Name = weapon.Name; + Icon = weapon.Icon; + Quality = weapon.Quality; + LevelCurrent = LevelMin; LevelTarget = LevelMax; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ImmutableIntrinsics.cs b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ImmutableIntrinsics.cs new file mode 100644 index 00000000..9c5b93b2 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ImmutableIntrinsics.cs @@ -0,0 +1,38 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Extension; +using System.Collections.Immutable; + +namespace Snap.Hutao.Model.Intrinsic; + +/// +/// 不可变的原生枚举 +/// +public static class ImmutableIntrinsics +{ + /// + /// 所属地区 + /// + public static readonly ImmutableList AssociationTypes = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); + + /// + /// 武器类型 + /// + public static readonly ImmutableList WeaponTypes = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); + + /// + /// 物品类型 + /// + public static readonly ImmutableList ItemQualities = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); + + /// + /// 身材类型 + /// + public static readonly ImmutableList BodyTypes = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); + + /// + /// 战斗属性 + /// + public static readonly ImmutableList FightProperties = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/WeaponType.cs b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/WeaponType.cs index 9d533f91..a0e594d0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/WeaponType.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/WeaponType.cs @@ -94,4 +94,4 @@ public enum WeaponType /// [Description("单手剑")] WEAPON_POLE = 13, -} \ No newline at end of file +} diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Achievement/AchievementGoal.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Achievement/AchievementGoal.cs index 853b8ad4..2396d89b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Achievement/AchievementGoal.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Achievement/AchievementGoal.cs @@ -31,5 +31,5 @@ public class AchievementGoal /// /// 图标 /// - public string? Icon { get; set; } + public string Icon { get; set; } = default!; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs index a950592c..d7997f5c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs @@ -4,6 +4,7 @@ using Snap.Hutao.Model.Binding.Gacha; using Snap.Hutao.Model.Binding.Gacha.Abstraction; using Snap.Hutao.Model.Binding.Hutao; +using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Metadata.Abstraction; using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs index 3f00c30b..0acfae5f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Calculable; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; namespace Snap.Hutao.Model.Metadata.Avatar; diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs index afa049d5..70d2f339 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs @@ -80,6 +80,8 @@ public static class AvatarIds public static readonly AvatarId Layla = 10000074; public static readonly AvatarId Wanderer = 10000075; public static readonly AvatarId Faruzan = 10000076; + public static readonly AvatarId Yaoyao = 10000077; + public static readonly AvatarId Alhaitham = 10000078; /// /// 检查该角色是否为主角 diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AchievementIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AchievementIconConverter.cs index 48b6b4db..a9e564a4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AchievementIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AchievementIconConverter.cs @@ -12,9 +12,19 @@ internal class AchievementIconConverter : ValueConverterBase { private const string BaseUrl = "https://static.snapgenshin.com/AchievementIcon/{0}.png"; + /// + /// 名称转Uri + /// + /// 名称 + /// 链接 + public static Uri IconNameToUri(string name) + { + return new Uri(string.Format(BaseUrl, name)); + } + /// public override Uri Convert(string from) { - return new Uri(string.Format(BaseUrl, from)); + return IconNameToUri(from); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs index f6f024ab..f4988703 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. using Snap.Hutao.Control; -using Snap.Hutao.Control.Image; +using Snap.Hutao.Control.Media; using Snap.Hutao.Model.Intrinsic; namespace Snap.Hutao.Model.Metadata.Converter; diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs index fe6f5ff6..7d04b39f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs @@ -4,6 +4,7 @@ using Snap.Hutao.Model.Binding.Gacha; using Snap.Hutao.Model.Binding.Gacha.Abstraction; using Snap.Hutao.Model.Binding.Hutao; +using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Abstraction; using Snap.Hutao.Model.Metadata.Converter; diff --git a/src/Snap.Hutao/Snap.Hutao/NativeMethods.txt b/src/Snap.Hutao/Snap.Hutao/NativeMethods.txt index 0c64a13b..1a601fd0 100644 --- a/src/Snap.Hutao/Snap.Hutao/NativeMethods.txt +++ b/src/Snap.Hutao/Snap.Hutao/NativeMethods.txt @@ -4,6 +4,8 @@ WM_GETMINMAXINFO WM_NCRBUTTONDOWN WM_NCRBUTTONUP +STDAPI + // Type definition CWMO_FLAGS HRESULT diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index 94f590ae..2e8b4b81 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -12,7 +12,7 @@ + Version="1.2.14.0" /> 胡桃 diff --git a/src/Snap.Hutao/Snap.Hutao/Program.cs b/src/Snap.Hutao/Snap.Hutao/Program.cs index b948b0ab..5d4047c2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Program.cs +++ b/src/Snap.Hutao/Snap.Hutao/Program.cs @@ -66,9 +66,7 @@ public static partial class Program ServiceProvider services = new ServiceCollection() // Microsoft extension - .AddLogging(builder => builder - .AddDebug() - .AddDatabase()) + .AddLogging(builder => builder.AddDebug().AddDatabase()) .AddMemoryCache() // Hutao extensions diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs index 1d43218b..98a2c640 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs @@ -9,7 +9,7 @@ using Snap.Hutao.Core.Diagnostics; using Snap.Hutao.Core.Logging; using Snap.Hutao.Model.InterChange.Achievement; using System.Collections.ObjectModel; -using BindingAchievement = Snap.Hutao.Model.Binding.Achievement; +using BindingAchievement = Snap.Hutao.Model.Binding.Achievement.Achievement; using EntityAchievement = Snap.Hutao.Model.Entity.Achievement; using EntityArchive = Snap.Hutao.Model.Entity.AchievementArchive; using MetadataAchievement = Snap.Hutao.Model.Metadata.Achievement.Achievement; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/IAchievementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/IAchievementService.cs index 8b69a8b5..a2bae36f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/IAchievementService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/IAchievementService.cs @@ -4,7 +4,7 @@ using Snap.Hutao.Core.Threading.CodeAnalysis; using Snap.Hutao.Model.InterChange.Achievement; using System.Collections.ObjectModel; -using BindingAchievement = Snap.Hutao.Model.Binding.Achievement; +using BindingAchievement = Snap.Hutao.Model.Binding.Achievement.Achievement; using EntityArchive = Snap.Hutao.Model.Entity.AchievementArchive; using MetadataAchievement = Snap.Hutao.Model.Metadata.Achievement.Achievement; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/AffixWeight.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/AffixWeight.cs index 76cc700f..c760775a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/AffixWeight.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/AffixWeight.cs @@ -15,28 +15,38 @@ internal class AffixWeight : Dictionary /// 构造一个新的词条权重 /// /// 角色Id - /// 大生命 - /// 大攻击 - /// 大防御 - /// 暴击率 - /// 暴击伤害 - /// 元素精通 - /// 充能效率 - /// 治疗加成 + /// 大生命 + /// 大攻击 + /// 大防御 + /// 暴击率 + /// 暴击伤害 + /// 元素精通 + /// 充能效率 + /// 治疗加成 /// 名称 - public AffixWeight(int avatarId, double hp, double atk, double def, double cr, double ch, double em, double ce, double ha, string name = "通用") + public AffixWeight( + int avatarId, + double hpPercent, + double attackPercenr, + double defensePercent, + double critical, + double criticalHurt, + double elementMastery, + double chargeEfficiency, + double healAdd, + string name = "通用") { AvatarId = avatarId; Name = name; - this[FightProperty.FIGHT_PROP_HP_PERCENT] = hp; - this[FightProperty.FIGHT_PROP_ATTACK_PERCENT] = atk; - this[FightProperty.FIGHT_PROP_DEFENSE_PERCENT] = def; - this[FightProperty.FIGHT_PROP_CRITICAL] = cr; - this[FightProperty.FIGHT_PROP_CRITICAL_HURT] = ch; - this[FightProperty.FIGHT_PROP_ELEMENT_MASTERY] = em; - this[FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY] = ce; - this[FightProperty.FIGHT_PROP_HEAL_ADD] = ha; + this[FightProperty.FIGHT_PROP_HP_PERCENT] = hpPercent; + this[FightProperty.FIGHT_PROP_ATTACK_PERCENT] = attackPercenr; + this[FightProperty.FIGHT_PROP_DEFENSE_PERCENT] = defensePercent; + this[FightProperty.FIGHT_PROP_CRITICAL] = critical; + this[FightProperty.FIGHT_PROP_CRITICAL_HURT] = criticalHurt; + this[FightProperty.FIGHT_PROP_ELEMENT_MASTERY] = elementMastery; + this[FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY] = chargeEfficiency; + this[FightProperty.FIGHT_PROP_HEAL_ADD] = healAdd; } /// @@ -48,4 +58,92 @@ internal class AffixWeight : Dictionary /// 名称 /// public string Name { get; } + + /// + /// 风元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Anemo(double value = 100) + { + this[FightProperty.FIGHT_PROP_WIND_ADD_HURT] = value; + return this; + } + + /// + /// 冰元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Cryo(double value = 100) + { + this[FightProperty.FIGHT_PROP_ICE_ADD_HURT] = value; + return this; + } + + /// + /// 草元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Dendro(double value = 100) + { + this[FightProperty.FIGHT_PROP_GRASS_ADD_HURT] = value; + return this; + } + + /// + /// 雷元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Electro(double value = 100) + { + this[FightProperty.FIGHT_PROP_ELEC_ADD_HURT] = value; + return this; + } + + /// + /// 岩元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Geo(double value = 100) + { + this[FightProperty.FIGHT_PROP_ROCK_ADD_HURT] = value; + return this; + } + + /// + /// 水元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Hydro(double value = 100) + { + this[FightProperty.FIGHT_PROP_WATER_ADD_HURT] = value; + return this; + } + + /// + /// 火元素伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Pyro(double value = 100) + { + this[FightProperty.FIGHT_PROP_FIRE_ADD_HURT] = value; + return this; + } + + /// + /// 物理伤害伤害加成 + /// + /// 值 + /// 链式调用对象 + public AffixWeight Phyiscal(double value = 100) + { + this[FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT] = value; + return this; + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs index de99489b..ce96c436 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs @@ -1,7 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata; namespace Snap.Hutao.Service.AvatarInfo.Factory; @@ -14,74 +13,74 @@ internal static partial class ReliquaryWeightConfiguration /// /// 默认 /// - public static readonly AffixWeight Default = new(0, 100, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }; + public static readonly AffixWeight Default = new(0, 100, 75, 0, 100, 100, 0, 55, 0); /// /// 词条权重 /// public static readonly List AffixWeights = new() { - new(AvatarIds.Ayaka, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Qin, 0, 75, 0, 100, 100, 0, 55, 100) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 100 } }, - new(AvatarIds.Lisa, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Barbara, 100, 50, 0, 50, 50, 0, 55, 100) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 80 } }, - new(AvatarIds.Barbara, 50, 75, 0, 100, 100, 0, 55, 100, "暴力奶妈") { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 100 } }, - new(AvatarIds.Kaeya, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Diluc, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Razor, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 50 }, { FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, 100 } }, - new(AvatarIds.Ambor, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Venti, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 100 } }, - new(AvatarIds.Xiangling, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Beidou, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Xingqiu, 0, 75, 0, 100, 100, 0, 75, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Xiao, 0, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 100 } }, - new(AvatarIds.Ningguang, 0, 75, 0, 100, 100, 0, 30, 0) { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 100 } }, - new(AvatarIds.Klee, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Zhongli, 80, 75, 0, 100, 100, 0, 55, 0, "武神钟离") { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 100 }, { FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, 50 } }, - new(AvatarIds.Zhongli, 100, 55, 0, 100, 100, 0, 55, 0, "血牛钟离") { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 75 } }, - new(AvatarIds.Zhongli, 100, 55, 0, 100, 100, 0, 75, 0, "血牛钟离(2命+)") { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 75 } }, - new(AvatarIds.Fischl, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Bennett, 100, 50, 0, 100, 100, 0, 55, 100) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 70 } }, - new(AvatarIds.Tartaglia, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Noel, 0, 50, 90, 100, 100, 0, 70, 0) { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 100 } }, - new(AvatarIds.Qiqi, 0, 100, 0, 100, 100, 0, 55, 100) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 60 } }, - new(AvatarIds.Chongyun, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Ganyu, 0, 75, 0, 100, 100, 75, 0, 0, "融化流") { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Ganyu, 0, 75, 0, 100, 100, 0, 55, 0, "永冻流") { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Albedo, 0, 0, 100, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 100 } }, - new(AvatarIds.Diona, 100, 50, 0, 50, 50, 0, 90, 100) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Mona, 0, 75, 0, 100, 100, 75, 75, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Keqing, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 }, { FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, 100 } }, - new(AvatarIds.Sucrose, 0, 75, 0, 100, 100, 100, 55, 0) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 40 } }, - new(AvatarIds.Xinyan, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 50 } }, - new(AvatarIds.Rosaria, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 70 }, { FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, 80 } }, - new(AvatarIds.Hutao, 80, 50, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Kazuha, 0, 75, 0, 100, 100, 100, 55, 0) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 100 } }, - new(AvatarIds.Feiyan, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Yoimiya, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 100 } }, - new(AvatarIds.Tohma, 100, 50, 0, 50, 50, 0, 90, 0) { { FightProperty.FIGHT_PROP_FIRE_ADD_HURT, 75 } }, - new(AvatarIds.Eula, 0, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 40 }, { FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, 100 } }, - new(AvatarIds.Shougun, 0, 75, 0, 100, 100, 0, 90, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 75 } }, - new(AvatarIds.Sayu, 0, 50, 0, 50, 50, 100, 55, 100) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 80 } }, - new(AvatarIds.Kokomi, 100, 50, 0, 0, 0, 0, 55, 100) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Gorou, 0, 50, 100, 50, 50, 0, 90, 0) { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 25 } }, - new(AvatarIds.Sara, 0, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Itto, 0, 50, 100, 100, 100, 0, 30, 0) { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 100 } }, - new(AvatarIds.Yae, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Heizou, 0, 75, 0, 100, 100, 75, 0, 0) { { FightProperty.FIGHT_PROP_WIND_ADD_HURT, 100 } }, - new(AvatarIds.Yelan, 80, 0, 0, 100, 100, 0, 75, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Aloy, 0, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Shenhe, 0, 100, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_ICE_ADD_HURT, 100 } }, - new(AvatarIds.Yunjin, 0, 0, 100, 50, 50, 0, 90, 0) { { FightProperty.FIGHT_PROP_ROCK_ADD_HURT, 25 } }, - new(AvatarIds.Shinobu, 100, 50, 0, 100, 100, 75, 55, 100) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Ayato, 50, 75, 0, 100, 100, 0, 0, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Collei, 0, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_GRASS_ADD_HURT, 100 } }, - new(AvatarIds.Dori, 100, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Tighnari, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_GRASS_ADD_HURT, 100 } }, - new(AvatarIds.Nilou, 100, 75, 0, 100, 100, 0, 55, 0, "直伤流") { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Nilou, 100, 75, 0, 100, 100, 0, 55, 0, "反应流") { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Cyno, 0, 75, 0, 100, 100, 75, 55, 0) { { FightProperty.FIGHT_PROP_ELEC_ADD_HURT, 100 } }, - new(AvatarIds.Candace, 100, 75, 0, 100, 100, 0, 55, 0) { { FightProperty.FIGHT_PROP_WATER_ADD_HURT, 100 } }, - new(AvatarIds.Nahida, 0, 55, 0, 100, 100, 100, 55, 0) { { FightProperty.FIGHT_PROP_GRASS_ADD_HURT, 100 } }, + new AffixWeight(AvatarIds.Ayaka, 0, 75, 0, 100, 100, 0, 0, 0).Cryo(), + new AffixWeight(AvatarIds.Qin, 0, 75, 0, 100, 100, 0, 55, 100).Anemo(), + 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, 0, 0).Cryo(), + 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(50).Phyiscal(), + new AffixWeight(AvatarIds.Ambor, 0, 75, 0, 100, 100, 75, 0, 0).Pyro(), + new AffixWeight(AvatarIds.Venti, 0, 75, 0, 100, 100, 75, 55, 0).Anemo(), + new AffixWeight(AvatarIds.Xiangling, 0, 75, 0, 100, 100, 75, 55, 0).Pyro(), + new AffixWeight(AvatarIds.Beidou, 0, 75, 0, 100, 100, 75, 55, 0).Electro(), + new AffixWeight(AvatarIds.Xingqiu, 0, 75, 0, 100, 100, 0, 75, 0).Hydro(), + new AffixWeight(AvatarIds.Xiao, 0, 75, 0, 100, 100, 0, 55, 0).Anemo(), + new AffixWeight(AvatarIds.Ningguang, 0, 75, 0, 100, 100, 0, 30, 0).Geo(), + new AffixWeight(AvatarIds.Klee, 0, 75, 0, 100, 100, 75, 0, 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, 0, 0, 0).Electro(), + new AffixWeight(AvatarIds.Bennett, 100, 50, 0, 100, 100, 0, 55, 100).Pyro(70), + new AffixWeight(AvatarIds.Tartaglia, 0, 75, 0, 100, 100, 75, 0, 0).Hydro(), + new AffixWeight(AvatarIds.Noel, 0, 50, 90, 100, 100, 0, 70, 0).Geo(), + new AffixWeight(AvatarIds.Qiqi, 0, 100, 0, 100, 100, 0, 55, 100).Cryo(60), + 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.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(), + new AffixWeight(AvatarIds.Keqing, 0, 75, 0, 100, 100, 0, 0, 0).Electro().Phyiscal(), + new AffixWeight(AvatarIds.Sucrose, 0, 75, 0, 100, 100, 100, 55, 0).Anemo(40), + new AffixWeight(AvatarIds.Xinyan, 0, 75, 0, 100, 100, 0, 0, 0).Pyro(50), + new AffixWeight(AvatarIds.Rosaria, 0, 75, 0, 100, 100, 0, 0, 0).Cryo(70).Phyiscal(80), + new AffixWeight(AvatarIds.Hutao, 80, 50, 0, 100, 100, 75, 0, 0).Pyro(), + new AffixWeight(AvatarIds.Kazuha, 0, 75, 0, 100, 100, 100, 55, 0).Anemo(), + new AffixWeight(AvatarIds.Feiyan, 0, 75, 0, 100, 100, 75, 0, 0).Pyro(), + new AffixWeight(AvatarIds.Yoimiya, 0, 75, 0, 100, 100, 75, 0, 0).Pyro(), + new AffixWeight(AvatarIds.Tohma, 100, 50, 0, 50, 50, 0, 90, 0).Pyro(75), + new AffixWeight(AvatarIds.Eula, 0, 75, 0, 100, 100, 0, 55, 0).Cryo(40).Phyiscal(100), + new AffixWeight(AvatarIds.Shougun, 0, 75, 0, 100, 100, 0, 90, 0).Electro(75), + new AffixWeight(AvatarIds.Sayu, 0, 50, 0, 50, 50, 100, 55, 100).Anemo(80), + new AffixWeight(AvatarIds.Kokomi, 100, 50, 0, 0, 0, 0, 55, 100).Hydro(), + new AffixWeight(AvatarIds.Gorou, 0, 50, 100, 50, 50, 0, 90, 0).Geo(25), + new AffixWeight(AvatarIds.Sara, 0, 75, 0, 100, 100, 0, 55, 0).Electro(), + new AffixWeight(AvatarIds.Itto, 0, 50, 100, 100, 100, 0, 30, 0).Geo(), + new AffixWeight(AvatarIds.Yae, 0, 75, 0, 100, 100, 75, 55, 0).Electro(), + new AffixWeight(AvatarIds.Heizou, 0, 75, 0, 100, 100, 75, 0, 0).Anemo(), + new AffixWeight(AvatarIds.Yelan, 80, 0, 0, 100, 100, 0, 75, 0).Hydro(), + new AffixWeight(AvatarIds.Aloy, 0, 75, 0, 100, 100, 0, 0, 0).Cryo(), + new AffixWeight(AvatarIds.Shenhe, 0, 100, 0, 100, 100, 0, 55, 0).Cryo(), + new AffixWeight(AvatarIds.Yunjin, 0, 0, 100, 50, 50, 0, 90, 0).Geo(25), + new AffixWeight(AvatarIds.Shinobu, 100, 50, 0, 100, 100, 75, 55, 100).Electro(), + new AffixWeight(AvatarIds.Ayato, 50, 75, 0, 100, 100, 0, 0, 0).Hydro(), + new AffixWeight(AvatarIds.Collei, 0, 75, 0, 100, 100, 0, 55, 0).Dendro(), + new AffixWeight(AvatarIds.Dori, 100, 75, 0, 100, 100, 0, 55, 0).Electro(), + new AffixWeight(AvatarIds.Tighnari, 0, 75, 0, 100, 100, 75, 55, 0).Dendro(), + new AffixWeight(AvatarIds.Nilou, 100, 75, 0, 100, 100, 0, 55, 0, "直伤流").Hydro(), + new AffixWeight(AvatarIds.Nilou, 100, 75, 0, 100, 100, 0, 55, 0, "反应流").Hydro(), + new AffixWeight(AvatarIds.Cyno, 0, 75, 0, 100, 100, 75, 55, 0).Electro(), + new AffixWeight(AvatarIds.Candace, 100, 75, 0, 100, 100, 0, 55, 0).Hydro(), + new AffixWeight(AvatarIds.Nahida, 0, 55, 0, 100, 100, 100, 55, 0).Dendro(), }; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs index 4481cfea..a01f343a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs @@ -5,11 +5,8 @@ using Snap.Hutao.Extension; using Snap.Hutao.Model; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Converter; -using Snap.Hutao.Model.Metadata.Reliquary; -using Snap.Hutao.Model.Primitive; using Snap.Hutao.Web.Enka.Model; using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar; -using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary; using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon; using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using PropertyAvatar = Snap.Hutao.Model.Binding.AvatarProperty.Avatar; @@ -23,40 +20,17 @@ namespace Snap.Hutao.Service.AvatarInfo.Factory; /// internal class SummaryAvatarFactory { - private readonly Dictionary idAvatarMap; - private readonly Dictionary idWeaponMap; - private readonly Dictionary idRelicMainPropMap; - private readonly Dictionary idReliquaryAffixMap; - private readonly List reliqueryLevels; - private readonly List reliquaries; - private readonly ModelAvatarInfo avatarInfo; + private readonly SummaryMetadataContext metadataContext; /// /// 构造一个新的角色工厂 /// - /// 角色映射 - /// 武器映射 - /// 圣遗物主属性映射 - /// 圣遗物副词条映射 - /// 圣遗物主属性等级 - /// 圣遗物 + /// 元数据上下文 /// 角色信息 - public SummaryAvatarFactory( - Dictionary idAvatarMap, - Dictionary idWeaponMap, - Dictionary idRelicMainPropMap, - Dictionary idReliquaryAffixMap, - List reliqueryLevels, - List reliquaries, - ModelAvatarInfo avatarInfo) + public SummaryAvatarFactory(SummaryMetadataContext metadataContext, ModelAvatarInfo avatarInfo) { - this.idAvatarMap = idAvatarMap; - this.idWeaponMap = idWeaponMap; - this.idRelicMainPropMap = idRelicMainPropMap; - this.idReliquaryAffixMap = idReliquaryAffixMap; - this.reliqueryLevels = reliqueryLevels; - this.reliquaries = reliquaries; + this.metadataContext = metadataContext; this.avatarInfo = avatarInfo; } @@ -67,10 +41,11 @@ internal class SummaryAvatarFactory public PropertyAvatar CreateAvatar() { ReliquaryAndWeapon reliquaryAndWeapon = ProcessEquip(avatarInfo.EquipList); - MetadataAvatar avatar = idAvatarMap[avatarInfo.AvatarId]; + MetadataAvatar avatar = metadataContext.IdAvatarMap[avatarInfo.AvatarId]; return new() { + Id = avatar.Id, Name = avatar.Name, Icon = AvatarIconConverter.IconNameToUri(avatar.Icon), SideIcon = AvatarIconConverter.IconNameToUri(avatar.SideIcon), @@ -78,6 +53,7 @@ internal class SummaryAvatarFactory Quality = avatar.Quality, Element = ElementNameIconConverter.ElementNameToElementType(avatar.FetterInfo.VisionBefore), Level = $"Lv.{avatarInfo.PropMap[PlayerProperty.PROP_LEVEL].Value}", + LevelNumber = int.Parse(avatarInfo.PropMap[PlayerProperty.PROP_LEVEL].Value ?? string.Empty), FetterLevel = avatarInfo.FetterInfo.ExpLevel, Weapon = reliquaryAndWeapon.Weapon, Reliquaries = reliquaryAndWeapon.Reliquaries, @@ -99,7 +75,7 @@ internal class SummaryAvatarFactory switch (equip.Flat.ItemType) { case ItemType.ITEM_RELIQUARY: - SummaryReliquaryFactory summaryReliquaryFactory = new(idReliquaryAffixMap, idRelicMainPropMap, reliqueryLevels, reliquaries, avatarInfo, equip); + SummaryReliquaryFactory summaryReliquaryFactory = new(metadataContext, avatarInfo, equip); reliquaryList.Add(summaryReliquaryFactory.CreateReliquary()); break; case ItemType.ITEM_WEAPON: @@ -113,7 +89,7 @@ internal class SummaryAvatarFactory private PropertyWeapon CreateWeapon(Equip equip) { - MetadataWeapon weapon = idWeaponMap[equip.ItemId]; + MetadataWeapon weapon = metadataContext.IdWeaponMap[equip.ItemId]; // AffixMap can be empty when it's a white weapon. KeyValuePair? idLevel = equip.Weapon!.AffixMap?.Single(); @@ -146,6 +122,8 @@ internal class SummaryAvatarFactory MainProperty = mainStat == null ? default! : new(mainStat.AppendPropId.GetDescription(), mainStat.StatValue.ToString()), // Weapon + Id = weapon.Id, + LevelNumber = equip.Weapon!.Level, SubProperty = subProperty, AffixLevel = $"精炼{affixLevel + 1}", AffixName = weapon.Affix?.Name ?? string.Empty, diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs index 03177b79..8cfa7896 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs @@ -2,13 +2,7 @@ // Licensed under the MIT license. using Snap.Hutao.Model.Binding.AvatarProperty; -using Snap.Hutao.Model.Intrinsic; -using Snap.Hutao.Model.Metadata.Reliquary; -using Snap.Hutao.Model.Primitive; using Snap.Hutao.Service.Metadata; -using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar; -using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary; -using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon; using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using ModelPlayerInfo = Snap.Hutao.Web.Enka.Model.PlayerInfo; @@ -34,15 +28,17 @@ internal class SummaryFactory : ISummaryFactory /// public async Task CreateAsync(ModelPlayerInfo playerInfo, IEnumerable avatarInfos, CancellationToken token) { - Dictionary idAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false); - Dictionary idWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false); - Dictionary idRelicMainPropMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false); - Dictionary idReliquaryAffixMap = await metadataService.GetIdReliquaryAffixMapAsync(token).ConfigureAwait(false); + SummaryMetadataContext metadataContext = new() + { + IdAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false), + IdWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false), + IdRelicMainPropMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false), + IdReliquaryAffixMap = await metadataService.GetIdReliquaryAffixMapAsync(token).ConfigureAwait(false), + ReliqueryLevels = await metadataService.GetReliquaryLevelsAsync(token).ConfigureAwait(false), + Reliquaries = await metadataService.GetReliquariesAsync(token).ConfigureAwait(false), + }; - List reliqueryLevels = await metadataService.GetReliquaryLevelsAsync(token).ConfigureAwait(false); - List reliquaries = await metadataService.GetReliquariesAsync(token).ConfigureAwait(false); - - SummaryFactoryImplementation inner = new(idAvatarMap, idWeaponMap, idRelicMainPropMap, idReliquaryAffixMap, reliqueryLevels, reliquaries); + SummaryFactoryImplementation inner = new(metadataContext); return inner.Create(playerInfo, avatarInfos); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactoryImplementation.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactoryImplementation.cs index dc604b71..20428588 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactoryImplementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactoryImplementation.cs @@ -2,13 +2,7 @@ // Licensed under the MIT license. using Snap.Hutao.Model.Binding.AvatarProperty; -using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata; -using Snap.Hutao.Model.Metadata.Reliquary; -using Snap.Hutao.Model.Primitive; -using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar; -using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary; -using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon; using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using ModelPlayerInfo = Snap.Hutao.Web.Enka.Model.PlayerInfo; @@ -19,36 +13,15 @@ namespace Snap.Hutao.Service.AvatarInfo.Factory; /// internal class SummaryFactoryImplementation { - private readonly Dictionary idAvatarMap; - private readonly Dictionary idWeaponMap; - private readonly Dictionary idRelicMainPropMap; - private readonly Dictionary idReliquaryAffixMap; - private readonly List reliqueryLevels; - private readonly List reliquaries; + private readonly SummaryMetadataContext metadataContext; /// /// 装配一个工厂实现 /// - /// 角色映射 - /// 武器映射 - /// 圣遗物主属性映射 - /// 圣遗物副词条映射 - /// 圣遗物主属性等级 - /// 圣遗物 - public SummaryFactoryImplementation( - Dictionary idAvatarMap, - Dictionary idWeaponMap, - Dictionary idRelicMainPropMap, - Dictionary idReliquaryAffixMap, - List reliqueryLevels, - List reliquaries) + /// 元数据上下文 + public SummaryFactoryImplementation(SummaryMetadataContext metadataContext) { - this.idAvatarMap = idAvatarMap; - this.idRelicMainPropMap = idRelicMainPropMap; - this.idWeaponMap = idWeaponMap; - this.reliqueryLevels = reliqueryLevels; - this.reliquaries = reliquaries; - this.idReliquaryAffixMap = idReliquaryAffixMap; + this.metadataContext = metadataContext; } /// @@ -64,14 +37,7 @@ internal class SummaryFactoryImplementation Player = SummaryHelper.CreatePlayer(playerInfo), Avatars = avatarInfos.Where(a => !AvatarIds.IsPlayer(a.AvatarId)).Select(a => { - SummaryAvatarFactory summaryAvatarFactory = new( - idAvatarMap, - idWeaponMap, - idRelicMainPropMap, - idReliquaryAffixMap, - reliqueryLevels, - reliquaries, - a); + SummaryAvatarFactory summaryAvatarFactory = new(metadataContext, a); return summaryAvatarFactory.CreateAvatar(); }).ToList(), }; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryHelper.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryHelper.cs index 2f26eb37..8d7ba8f2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryHelper.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryHelper.cs @@ -88,7 +88,8 @@ internal static class SummaryHelper Icon = SkillIconConverter.IconNameToUri(proudableSkill.Icon), Description = proudableSkill.Description, - Level = skillLevelMap[proudableSkill.Id.ToString()], + GroupId = proudableSkill.GroupId, + LevelNumber = skillLevelMap[proudableSkill.Id.ToString()], Info = DescParamDescriptor.Convert(proudableSkill.Proud, skillExtraLeveledMap[proudableSkill.Id.ToString()]), }; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryMetadataContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryMetadataContext.cs new file mode 100644 index 00000000..14f8e8d8 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryMetadataContext.cs @@ -0,0 +1,31 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Binding.AvatarProperty; +using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Metadata.Reliquary; +using Snap.Hutao.Model.Primitive; +using Snap.Hutao.Service.Metadata; +using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar; +using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary; +using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon; +using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; +using ModelPlayerInfo = Snap.Hutao.Web.Enka.Model.PlayerInfo; + +namespace Snap.Hutao.Service.AvatarInfo.Factory; + +[SuppressMessage("", "SA1600")] +internal class SummaryMetadataContext +{ + public Dictionary IdAvatarMap { get; set; } = default!; + + public Dictionary IdWeaponMap { get; set; } = default!; + + public Dictionary IdRelicMainPropMap { get; set; } = default!; + + public Dictionary IdReliquaryAffixMap { get; set; } = default!; + + public List ReliqueryLevels { get; set; } = default!; + + public List Reliquaries { get; set; } = default!; +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryReliquaryFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryReliquaryFactory.cs index ad2810c7..6095da73 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryReliquaryFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryReliquaryFactory.cs @@ -7,7 +7,6 @@ using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Annotation; using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Model.Metadata.Reliquary; -using Snap.Hutao.Model.Primitive; using Snap.Hutao.Web.Enka.Model; using System.Runtime.InteropServices; using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary; @@ -22,36 +21,19 @@ namespace Snap.Hutao.Service.AvatarInfo.Factory; /// internal class SummaryReliquaryFactory { - private readonly Dictionary idReliquaryAffixMap; - private readonly Dictionary idRelicMainPropMap; - private readonly List reliqueryLevels; - private readonly List reliquaries; - + private readonly SummaryMetadataContext metadataContext; private readonly ModelAvatarInfo avatarInfo; private readonly Equip equip; /// /// 构造一个新的圣遗物工厂 /// - /// 圣遗物副词条映射 - /// 圣遗物主属性映射 - /// 圣遗物主属性等级 - /// 圣遗物列表 + /// 元数据上下文 /// 角色信息 /// 圣遗物 - public SummaryReliquaryFactory( - Dictionary idReliquaryAffixMap, - Dictionary idRelicMainPropMap, - List reliqueryLevels, - List reliquaries, - ModelAvatarInfo avatarInfo, - Equip equip) + public SummaryReliquaryFactory(SummaryMetadataContext metadataContext, ModelAvatarInfo avatarInfo, Equip equip) { - this.idReliquaryAffixMap = idReliquaryAffixMap; - this.idRelicMainPropMap = idRelicMainPropMap; - this.reliqueryLevels = reliqueryLevels; - this.reliquaries = reliquaries; - + this.metadataContext = metadataContext; this.avatarInfo = avatarInfo; this.equip = equip; } @@ -62,7 +44,7 @@ internal class SummaryReliquaryFactory /// 圣遗物 public PropertyReliquary CreateReliquary() { - MetadataReliquary reliquary = reliquaries.Single(r => r.Ids.Contains(equip.ItemId)); + MetadataReliquary reliquary = metadataContext.Reliquaries.Single(r => r.Ids.Contains(equip.ItemId)); List subProperty = equip.Reliquary!.AppendPropIdList.EmptyIfNull().Select(CreateSubProperty).ToList(); int affixCount = GetAffixCount(reliquary); @@ -87,8 +69,8 @@ internal class SummaryReliquaryFactory List composed = equip.Flat.ReliquarySubstats!.Select(CreateComposedSubProperty).ToList(); - ReliquaryLevel relicLevel = reliqueryLevels.Single(r => r.Level == equip.Reliquary!.Level && r.Quality == reliquary.RankLevel); - FightProperty property = idRelicMainPropMap[equip.Reliquary.MainPropId]; + ReliquaryLevel relicLevel = metadataContext.ReliqueryLevels.Single(r => r.Level == equip.Reliquary!.Level && r.Quality == reliquary.RankLevel); + FightProperty property = metadataContext.IdRelicMainPropMap[equip.Reliquary.MainPropId]; return new() { @@ -148,7 +130,7 @@ internal class SummaryReliquaryFactory if (equip.Flat.EquipType is EquipType.EQUIP_SHOES or EquipType.EQUIP_RING or EquipType.EQUIP_DRESS) { AffixWeight weightConfig = GetAffixWeightForAvatarId(); - ReliquaryLevel maxRelicLevel = reliqueryLevels.Where(r => r.Quality == reliquary.RankLevel).MaxBy(r => r.Level)!; + ReliquaryLevel maxRelicLevel = metadataContext.ReliqueryLevels.Where(r => r.Quality == reliquary.RankLevel).MaxBy(r => r.Level)!; double percent = relicLevel.Properties[property] / maxRelicLevel.Properties[property]; double baseScore = 8 * percent * weightConfig.GetValueOrDefault(property, 0); @@ -183,7 +165,7 @@ internal class SummaryReliquaryFactory private ReliquarySubProperty CreateSubProperty(int appendPropId) { - MetadataReliquaryAffix affix = idReliquaryAffixMap[appendPropId]; + MetadataReliquaryAffix affix = metadataContext.IdReliquaryAffixMap[appendPropId]; FightProperty property = affix.Type; double score = ScoreSubAffix(appendPropId); @@ -192,7 +174,7 @@ internal class SummaryReliquaryFactory private double ScoreSubAffix(int appendId) { - MetadataReliquaryAffix affix = idReliquaryAffixMap[appendId]; + MetadataReliquaryAffix affix = metadataContext.IdReliquaryAffixMap[appendId]; AffixWeight weightConfig = GetAffixWeightForAvatarId(); double weight = weightConfig.GetValueOrDefault(affix.Type, 0) / 100D; @@ -200,14 +182,14 @@ internal class SummaryReliquaryFactory // 小字词条,转换到等效百分比计算 if (affix.Type is FightProperty.FIGHT_PROP_HP or FightProperty.FIGHT_PROP_ATTACK or FightProperty.FIGHT_PROP_DEFENSE) { - // 等效百分比 [ 当前小字词条 / 角色基本属性 ] + // 等效百分比 [ 当前小字词条 / 角色基本属性 ] double equalPercent = affix.Value / avatarInfo.FightPropMap[affix.Type - 1]; // 获取对应百分比词条权重 weight = weightConfig.GetValueOrDefault(affix.Type + 1, 0) / 100D; // 最大同属性百分比数值 最大同属性百分比Id 第四五位是战斗属性位 - MetadataReliquaryAffix maxPercentAffix = idReliquaryAffixMap[SummaryHelper.GetAffixMaxId(appendId + 10)]; + MetadataReliquaryAffix maxPercentAffix = metadataContext.IdReliquaryAffixMap[SummaryHelper.GetAffixMaxId(appendId + 10)]; double equalScore = equalPercent / maxPercentAffix.Value; return weight * equalScore * 100; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs index a4ce86c0..4f11e774 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs @@ -131,7 +131,7 @@ internal class CultivationService : ICultivationService /// public async Task> GetCultivateEntriesAsync( CultivateProject cultivateProject, - List metadata, + List materials, Dictionary idAvatarMap, Dictionary idWeaponMap) { @@ -160,7 +160,7 @@ internal class CultivationService : ICultivationService foreach (CultivateItem item in items) { - resultItems.Add(new(metadata.Single(m => m.Id == item.ItemId), item)); + resultItems.Add(new(materials.Single(m => m.Id == item.ItemId), item)); } Model.Binding.Gacha.Abstraction.ItemBase itemBase = entry.Type switch @@ -209,6 +209,11 @@ internal class CultivationService : ICultivationService /// public async Task SaveConsumptionAsync(Model.Binding.Cultivation.CultivateType type, int itemId, List items) { + if (items.Count == 0) + { + return true; + } + using (IServiceScope scope = scopeFactory.CreateScope()) { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs index ed5df53c..f6e12b88 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs @@ -24,11 +24,11 @@ internal interface ICultivationService /// 获取绑定用的养成列表 /// /// 养成计划 - /// 材料 + /// 材料 /// Id角色映射 /// Id武器映射 /// 绑定用的养成列表 - Task> GetCultivateEntriesAsync(CultivateProject cultivateProject, List metadata, Dictionary idAvatarMap, Dictionary idWeaponMap); + Task> GetCultivateEntriesAsync(CultivateProject cultivateProject, List materials, Dictionary idAvatarMap, Dictionary idWeaponMap); /// /// 获取物品列表 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs index 6c367dcc..130b29b1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs @@ -17,7 +17,6 @@ namespace Snap.Hutao.Service.DailyNote; internal class DailyNoteNotifier { private readonly IServiceScopeFactory scopeFactory; - private readonly BindingClient bindingClient; private readonly DailyNoteEntry entry; /// @@ -26,10 +25,9 @@ internal class DailyNoteNotifier /// 范围工厂 /// 绑定客户端 /// 实时便笺入口 - public DailyNoteNotifier(IServiceScopeFactory scopeFactory, BindingClient bindingClient, DailyNoteEntry entry) + public DailyNoteNotifier(IServiceScopeFactory scopeFactory, DailyNoteEntry entry) { this.scopeFactory = scopeFactory; - this.bindingClient = bindingClient; this.entry = entry; } @@ -119,37 +117,39 @@ internal class DailyNoteNotifier return; } - List roles = await bindingClient.GetUserGameRolesByCookieAsync(entry.User).ConfigureAwait(false); - string attribution = roles.SingleOrDefault(r => r.GameUid == entry.Uid)?.ToString() ?? "未知角色"; - - ToastContentBuilder builder = new ToastContentBuilder() - .AddHeader("DAILYNOTE", "实时便笺提醒", "DAILYNOTE") - .AddAttributionText(attribution) - .AddButton(new ToastButton().SetContent("开始游戏").AddArgument("Action", "LaunchGame").AddArgument("Uid", entry.Uid)) - .AddButton(new ToastButtonDismiss("我知道了")); - using (IServiceScope scope = scopeFactory.CreateScope()) { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); + BindingClient bindingClient = scope.ServiceProvider.GetRequiredService(); + + List roles = await bindingClient.GetUserGameRolesByCookieAsync(entry.User).ConfigureAwait(false); + string attribution = roles.SingleOrDefault(r => r.GameUid == entry.Uid)?.ToString() ?? "未知角色"; + + ToastContentBuilder builder = new ToastContentBuilder() + .AddHeader("DAILYNOTE", "实时便笺提醒", "DAILYNOTE") + .AddAttributionText(attribution) + .AddButton(new ToastButton().SetContent("开始游戏").AddArgument("Action", "LaunchGame").AddArgument("Uid", entry.Uid)) + .AddButton(new ToastButtonDismiss("我知道了")); + if (appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteReminderNotify, SettingEntryHelper.FalseString).GetBoolean()) { builder.SetToastScenario(ToastScenario.Reminder); } - } - if (hints.Count > 2) - { - builder.AddText("多个提醒项达到设定值"); - } - else - { - foreach (string hint in hints) + if (hints.Count > 2) { - builder.AddText(hint); + builder.AddText("多个提醒项达到设定值"); + } + else + { + foreach (string hint in hints) + { + builder.AddText(hint); + } } - } - await ThreadHelper.SwitchToMainThreadAsync(); - builder.Show(); + await ThreadHelper.SwitchToMainThreadAsync(); + builder.Show(); + } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs index aceeb2ee..79a3a8a4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs @@ -61,9 +61,9 @@ internal class DailyNoteService : IDailyNoteService, IRecipient(); List entryList = appDbContext.DailyNotes.AsNoTracking().ToList(); entryList.ForEach(entry => { entry.UserGameRole = userService.GetUserGameRoleByUid(entry.Uid); }); - entries = new(appDbContext.DailyNotes); + entries = new(entryList); } } @@ -96,7 +96,6 @@ internal class DailyNoteService : IDailyNoteService, IRecipient(); GameRecordClient gameRecordClient = scope.ServiceProvider.GetRequiredService(); - BindingClient bindingClient = scope.ServiceProvider.GetRequiredService(); foreach (DailyNoteEntry entry in appDbContext.DailyNotes.Include(n => n.User)) { @@ -111,7 +110,7 @@ internal class DailyNoteService : IDailyNoteService, IRecipient> list) { descParamComboBox.ItemHost.ItemsSource = list; - descParamComboBox.ItemHost.SelectedIndex = Math.Min(descParamComboBox.PreferredSelectedIndex, list.Count); + descParamComboBox.ItemHost.SelectedIndex = Math.Min(descParamComboBox.PreferredSelectedIndex, list.Count - 1); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml index 73dc58f2..d9db0832 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml @@ -30,6 +30,12 @@ + + @@ -73,7 +79,10 @@ Label="删除当前存档"/> - + @@ -114,21 +123,31 @@ SelectionMode="Single"> - + - + - + Width="36" + Height="36" + Source="{Binding Icon}"/> + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AvatarPropertyPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AvatarPropertyPage.xaml index ec4ef4f4..f404cced 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/AvatarPropertyPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AvatarPropertyPage.xaml @@ -58,6 +58,11 @@ CommandParameter="{Binding ElementName=ImageExportPanel}" Icon="{shcm:FontIcon Glyph=}" Label="导出图片"/> + @@ -129,7 +134,7 @@ - + - - - - - - - - - - - - - diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml index 83a7bd29..1dddd568 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml @@ -71,7 +71,7 @@ diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml index 01d86a11..d62da498 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml @@ -249,7 +249,7 @@ Margin="0,16,0,8" Style="{StaticResource BaseTextBlockStyle}" Text="五星"/> - + @@ -276,7 +276,7 @@ Margin="0,0,0,8" Style="{StaticResource BaseTextBlockStyle}" Text="四星"/> - + @@ -303,7 +303,7 @@ Margin="0,0,0,8" Style="{StaticResource BaseTextBlockStyle}" Text="三星"/> - + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml index 9e24f287..42681b42 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml @@ -65,6 +65,10 @@ Text="{Binding DeviceId}"/> + + + + public ICommand ExportAsImageCommand { get; } - private static unsafe void NormalBlend(SoftwareBitmap softwareBitmap, Bgra8 tint) - { - using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) - { - using (IMemoryBufferReference reference = buffer.CreateReference()) - { - reference.As().GetBuffer(out byte* data, out uint length); - - for (int i = 0; i < length; i += 4) - { - Bgra8* pixel = (Bgra8*)(data + i); - byte baseAlpha = pixel->A; - pixel->B = (byte)(((pixel->B * baseAlpha) + (tint.B * (0xFF - baseAlpha))) / 0xFF); - pixel->G = (byte)(((pixel->G * baseAlpha) + (tint.G * (0xFF - baseAlpha))) / 0xFF); - pixel->R = (byte)(((pixel->R * baseAlpha) + (tint.R * (0xFF - baseAlpha))) / 0xFF); - pixel->A = 0xFF; - } - } - } - } + /// + /// 养成命令 + /// + public ICommand CultivateCommand { get; } private Task OpenUIAsync() { @@ -205,6 +195,58 @@ internal class AvatarPropertyViewModel : ObservableObject, ISupportCancellation } } + private async Task CultivateAsync(Avatar? avatar) + { + if (avatar != null) + { + IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + IUserService userService = Ioc.Default.GetRequiredService(); + + if (userService.Current != null) + { + MainWindow mainWindow = Ioc.Default.GetRequiredService(); + (bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(mainWindow, avatar.ToCalculable(), avatar.Weapon.ToCalculable()) + .GetPromotionDeltaAsync() + .ConfigureAwait(false); + + if (isOk) + { + CalcConsumption? consumption = await Ioc.Default + .GetRequiredService() + .ComputeAsync(userService.Current.Entity, delta) + .ConfigureAwait(false); + + if (consumption != null) + { + List items = CalcItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume); + bool avatarSaved = await Ioc.Default + .GetRequiredService() + .SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items) + .ConfigureAwait(false); + + bool weaponSaved = await Ioc.Default + .GetRequiredService() + .SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull()) + .ConfigureAwait(false); + + if (avatarSaved && weaponSaved) + { + infoBarService.Success("已成功添加至当前养成计划"); + } + else + { + infoBarService.Warning("请先前往养成计划页面创建计划并选中"); + } + } + } + } + else + { + infoBarService.Warning("必须先选择一个用户与角色"); + } + } + } + private async Task ExportAsImageAsync(UIElement? element) { if (element == null) @@ -219,7 +261,7 @@ internal class AvatarPropertyViewModel : ObservableObject, ISupportCancellation SoftwareBitmap softwareBitmap = SoftwareBitmap.CreateCopyFromBuffer(buffer, BitmapPixelFormat.Bgra8, bitmap.PixelWidth, bitmap.PixelHeight, BitmapAlphaMode.Ignore); Color tintColor = (Color)Ioc.Default.GetRequiredService().Resources["CompatBackgroundColor"]; Bgra8 tint = Bgra8.FromColor(tintColor); - NormalBlend(softwareBitmap, tint); + softwareBitmap.NormalBlend(tint); using (InMemoryRandomAccessStream memory = new()) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs index 07ff3c9d..d5c965af 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs @@ -93,7 +93,7 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation { refreshSecondsEntry!.SetInt32(value.Value); appDbContext.Settings.UpdateAndSave(refreshSecondsEntry!); - TaskSchedulerHelper.RegisterForDailyNoteRefresh(value.Value); + ScheduleTaskHelper.RegisterForDailyNoteRefresh(value.Value); } } } @@ -161,7 +161,7 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation refreshSecondsEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteRefreshSeconds, "480"); selectedRefreshTime = refreshTimes.Single(t => t.Value == refreshSecondsEntry.GetInt32()); - TaskSchedulerHelper.RegisterForDailyNoteRefresh(480); + ScheduleTaskHelper.RegisterForDailyNoteRefresh(480); OnPropertyChanged(nameof(SelectedRefreshTime)); reminderNotifyEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteReminderNotify, false.ToString()); diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs index ab93755b..f70928dc 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Context.Database; @@ -38,7 +39,8 @@ internal class ExperimentalFeaturesViewModel : ObservableObject OpenCacheFolderCommand = asyncRelayCommandFactory.Create(OpenCacheFolderAsync); OpenDataFolderCommand = asyncRelayCommandFactory.Create(OpenDataFolderAsync); UploadSpiralAbyssRecordCommand = asyncRelayCommandFactory.Create(UploadSpiralAbyssRecordAsync); - DeleteUsersCommand = asyncRelayCommandFactory.Create(DeleteUsersAsync); + DeleteUsersCommand = asyncRelayCommandFactory.Create(DangerousDeleteUsersAsync); + DeleteAllScheduleTasksCommand = new RelayCommand(DangerousDeleteAllScheduleTasks); } /// @@ -61,6 +63,11 @@ internal class ExperimentalFeaturesViewModel : ObservableObject /// public ICommand DeleteUsersCommand { get; } + /// + /// 删除所有计划任务命令 + /// + public ICommand DeleteAllScheduleTasksCommand { get; } + private Task OpenCacheFolderAsync() { return Launcher.LaunchFolderAsync(ApplicationData.Current.TemporaryFolder).AsTask(); @@ -94,7 +101,7 @@ internal class ExperimentalFeaturesViewModel : ObservableObject } } - private async Task DeleteUsersAsync() + private async Task DangerousDeleteUsersAsync() { using (IServiceScope scope = Ioc.Default.CreateScope()) { @@ -105,4 +112,17 @@ internal class ExperimentalFeaturesViewModel : ObservableObject infoBarService.Success("清除用户数据成功,请重启胡桃"); } } + + private void DangerousDeleteAllScheduleTasks() + { + IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + if (Core.ScheduleTaskHelper.UnregisterAllTasks()) + { + infoBarService.Success("清除任务计划成功"); + } + else + { + infoBarService.Warning("清除任务计划失败"); + } + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs index 77986802..aeb320ef 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs @@ -93,6 +93,15 @@ internal class SettingViewModel : ObservableObject get => Core.CoreEnvironment.Version.ToString(); } + /// + /// Webview2 版本 + /// + [SuppressMessage("", "CA1822")] + public string WebView2Version + { + get => Core.WebView2Helper.Version; + } + /// /// 设备Id /// diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs index 2e682eb3..b1c31087 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs @@ -185,11 +185,6 @@ internal class WikiAvatarViewModel : ObservableObject private static class AvatarFilter { - private static readonly ImmutableList AssociationTypes = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); - private static readonly ImmutableList WeaponTypes = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); - private static readonly ImmutableList ItemQualities = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); - private static readonly ImmutableList BodyTypes = Enum.GetValues().Select(e => e.GetDescriptionOrNull()).OfType().ToImmutableList(); - public static Predicate Compile(string input) { return (object o) => o is Avatar avatar && DoFilter(input, avatar); @@ -209,25 +204,25 @@ internal class WikiAvatarViewModel : ObservableObject continue; } - if (AssociationTypes.Contains(value)) + if (ImmutableIntrinsics.AssociationTypes.Contains(value)) { keep = keep || avatar.FetterInfo.Association.GetDescriptionOrNull() == value; continue; } - if (WeaponTypes.Contains(value)) + if (ImmutableIntrinsics.WeaponTypes.Contains(value)) { keep = keep || avatar.Weapon.GetDescriptionOrNull() == value; continue; } - if (ItemQualities.Contains(value)) + if (ImmutableIntrinsics.ItemQualities.Contains(value)) { keep = keep || avatar.Quality.GetDescriptionOrNull() == value; continue; } - if (BodyTypes.Contains(value)) + if (ImmutableIntrinsics.BodyTypes.Contains(value)) { keep = keep || avatar.Body.GetDescriptionOrNull() == value; continue; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs index 38bae40f..e4a9edb1 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs @@ -2,12 +2,15 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using CommunityToolkit.WinUI.UI; +using Microsoft.Extensions.Primitives; using Snap.Hutao.Control; using Snap.Hutao.Extension; using Snap.Hutao.Factory.Abstraction; using Snap.Hutao.Model.Binding.Cultivation; using Snap.Hutao.Model.Binding.Hutao; +using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Weapon; using Snap.Hutao.Model.Primitive; using Snap.Hutao.Service.Abstraction; @@ -16,6 +19,7 @@ using Snap.Hutao.Service.Hutao; using Snap.Hutao.Service.Metadata; using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; +using System.Collections.Immutable; using CalcAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta; using CalcClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient; using CalcConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption; @@ -39,6 +43,7 @@ internal class WikiWeaponViewModel : ObservableObject, ISupportCancellation private AdvancedCollectionView? weapons; private Weapon? selected; + private string? filterText; /// /// 构造一个新的武器资料视图模型 @@ -53,6 +58,7 @@ internal class WikiWeaponViewModel : ObservableObject, ISupportCancellation OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync); CultivateCommand = asyncRelayCommandFactory.Create(CultivateAsync); + FilterCommand = new RelayCommand(ApplyFilter); } /// @@ -68,6 +74,11 @@ internal class WikiWeaponViewModel : ObservableObject, ISupportCancellation /// public Weapon? Selected { get => selected; set => SetProperty(ref selected, value); } + /// + /// 筛选文本 + /// + public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); } + /// /// 打开界面命令 /// @@ -78,6 +89,11 @@ internal class WikiWeaponViewModel : ObservableObject, ISupportCancellation /// public ICommand CultivateCommand { get; } + /// + /// 筛选命令 + /// + public ICommand FilterCommand { get; } + private async Task OpenUIAsync() { if (await metadataService.InitializeAsync().ConfigureAwait(false)) @@ -152,4 +168,67 @@ internal class WikiWeaponViewModel : ObservableObject, ISupportCancellation } } } + + private void ApplyFilter(string? input) + { + if (Weapons != null) + { + if (!string.IsNullOrWhiteSpace(input)) + { + Weapons.Filter = WeaponFilter.Compile(input); + + if (!Weapons.Contains(Selected)) + { + Weapons.MoveCurrentToFirst(); + } + } + else + { + Weapons.Filter = null!; + } + } + } + + private static class WeaponFilter + { + public static Predicate Compile(string input) + { + return (object o) => o is Weapon weapon && DoFilter(input, weapon); + } + + private static bool DoFilter(string input, Weapon weapon) + { + bool keep = false; + + foreach (StringSegment segment in new StringTokenizer(input, ' '.Enumerate().ToArray())) + { + string value = segment.ToString(); + + if (ImmutableIntrinsics.WeaponTypes.Contains(value)) + { + keep = keep || weapon.WeaponType.GetDescriptionOrNull() == value; + continue; + } + + if (ImmutableIntrinsics.ItemQualities.Contains(value)) + { + keep = keep || weapon.Quality.GetDescriptionOrNull() == value; + continue; + } + + if (ImmutableIntrinsics.FightProperties.Contains(value)) + { + keep = keep || weapon.Property.Properties.ElementAtOrDefault(1).GetDescriptionOrNull() == value; + continue; + } + + if (weapon.Name == value) + { + keep = true; + } + } + + return keep; + } + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Annotation/IgnoreSetCookieAttribute.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Annotation/IgnoreSetCookieAttribute.cs deleted file mode 100644 index e93b7f51..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Annotation/IgnoreSetCookieAttribute.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Web.Hoyolab.Annotation; - -/// -/// 指示相关的类忽略Http请求的Set-Cookie头 -/// -[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] -internal class IgnoreSetCookieAttribute : Attribute -{ -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs index 9c038385..51f728c2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs @@ -11,7 +11,6 @@ namespace Snap.Hutao.Web.Hoyolab.Bbs.User; /// /// 用户信息客户端 /// -[IgnoreSetCookie] [HttpClient(HttpClientConfigration.XRpc)] internal class UserClient {