mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
batch add for avatarinfo cultivation
This commit is contained in:
@@ -63,4 +63,17 @@ internal static class SettingKeys
|
|||||||
/// 覆盖管理员权限执行命令
|
/// 覆盖管理员权限执行命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string OverrideElevationRequirement = "OverrideElevationRequirement";
|
public const string OverrideElevationRequirement = "OverrideElevationRequirement";
|
||||||
|
|
||||||
|
public const string CultivationAvatarLevelCurrent = "CultivationAvatarLevelCurrent";
|
||||||
|
public const string CultivationAvatarLevelTarget = "CultivationAvatarLevelTarget";
|
||||||
|
public const string CultivationAvatarSkillACurrent = "CultivationAvatarSkillACurrent";
|
||||||
|
public const string CultivationAvatarSkillATarget = "CultivationAvatarSkillATarget";
|
||||||
|
public const string CultivationAvatarSkillECurrent = "CultivationAvatarSkillECurrent";
|
||||||
|
public const string CultivationAvatarSkillETarget = "CultivationAvatarSkillETarget";
|
||||||
|
public const string CultivationAvatarSkillQCurrent = "CultivationAvatarSkillQCurrent";
|
||||||
|
public const string CultivationAvatarSkillQTarget = "CultivationAvatarSkillQTarget";
|
||||||
|
public const string CultivationWeapon90LevelCurrent = "CultivationWeapon90LevelCurrent";
|
||||||
|
public const string CultivationWeapon90LevelTarget = "CultivationWeapon90LevelTarget";
|
||||||
|
public const string CultivationWeapon70LevelCurrent = "CultivationWeapon70LevelCurrent";
|
||||||
|
public const string CultivationWeapon70LevelTarget = "CultivationWeapon70LevelTarget";
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ internal static partial class EnumerableExtension
|
|||||||
Span<TSource> span = CollectionsMarshal.AsSpan(list);
|
Span<TSource> span = CollectionsMarshal.AsSpan(list);
|
||||||
List<TResult> results = new(span.Length);
|
List<TResult> results = new(span.Length);
|
||||||
|
|
||||||
foreach (TSource item in span)
|
foreach (ref readonly TSource item in span)
|
||||||
{
|
{
|
||||||
results.Add(selector(item));
|
results.Add(selector(item));
|
||||||
}
|
}
|
||||||
@@ -111,6 +111,21 @@ internal static partial class EnumerableExtension
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Pure]
|
||||||
|
public static List<TResult> SelectList<TSource, TResult>(this List<TSource> list, Func<TSource, int, TResult> selector)
|
||||||
|
{
|
||||||
|
Span<TSource> span = CollectionsMarshal.AsSpan(list);
|
||||||
|
List<TResult> results = new(span.Length);
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
foreach (ref readonly TSource item in span)
|
||||||
|
{
|
||||||
|
results.Add(selector(item, ++index));
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
public static async ValueTask<List<TResult>> SelectListAsync<TSource, TResult>(this List<TSource> list, Func<TSource, ValueTask<TResult>> selector)
|
public static async ValueTask<List<TResult>> SelectListAsync<TSource, TResult>(this List<TSource> list, Func<TSource, ValueTask<TResult>> selector)
|
||||||
{
|
{
|
||||||
List<TResult> results = new(list.Count);
|
List<TResult> results = new(list.Count);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Snap.Hutao.Core.Abstraction;
|
using Snap.Hutao.Core.Abstraction;
|
||||||
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Metadata.Avatar;
|
using Snap.Hutao.Model.Metadata.Avatar;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
@@ -21,9 +22,6 @@ internal sealed class CalculableAvatar
|
|||||||
IMappingFrom<CalculableAvatar, Avatar>,
|
IMappingFrom<CalculableAvatar, Avatar>,
|
||||||
IMappingFrom<CalculableAvatar, AvatarView>
|
IMappingFrom<CalculableAvatar, AvatarView>
|
||||||
{
|
{
|
||||||
private uint levelCurrent;
|
|
||||||
private uint levelTarget;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的可计算角色
|
/// 构造一个新的可计算角色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -32,14 +30,11 @@ internal sealed class CalculableAvatar
|
|||||||
{
|
{
|
||||||
AvatarId = avatar.Id;
|
AvatarId = avatar.Id;
|
||||||
LevelMin = 1;
|
LevelMin = 1;
|
||||||
LevelMax = 90;
|
LevelMax = avatar.MaxLevel;
|
||||||
Skills = avatar.SkillDepot.CompositeSkillsNoInherents().SelectList(p => p.ToCalculable());
|
Skills = avatar.SkillDepot.CompositeSkillsNoInherents().SelectList((p, i) => p.ToCalculable((SkillType)i));
|
||||||
Name = avatar.Name;
|
Name = avatar.Name;
|
||||||
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
||||||
Quality = avatar.Quality;
|
Quality = avatar.Quality;
|
||||||
|
|
||||||
LevelCurrent = LevelMin;
|
|
||||||
LevelTarget = LevelMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -50,14 +45,11 @@ internal sealed class CalculableAvatar
|
|||||||
{
|
{
|
||||||
AvatarId = avatar.Id;
|
AvatarId = avatar.Id;
|
||||||
LevelMin = avatar.LevelNumber;
|
LevelMin = avatar.LevelNumber;
|
||||||
LevelMax = 90; // hard coded 90
|
LevelMax = Avatar.GetMaxLevel();
|
||||||
Skills = avatar.Skills.SelectList(s => s.ToCalculable());
|
Skills = avatar.Skills.SelectList((s, i) => s.ToCalculable((SkillType)i));
|
||||||
Name = avatar.Name;
|
Name = avatar.Name;
|
||||||
Icon = avatar.Icon;
|
Icon = avatar.Icon;
|
||||||
Quality = avatar.Quality;
|
Quality = avatar.Quality;
|
||||||
|
|
||||||
LevelCurrent = LevelMin;
|
|
||||||
LevelTarget = LevelMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -82,10 +74,18 @@ internal sealed class CalculableAvatar
|
|||||||
public QualityType Quality { get; }
|
public QualityType Quality { get; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint LevelCurrent { get => levelCurrent; set => SetProperty(ref levelCurrent, value); }
|
public uint LevelCurrent
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeys.CultivationAvatarLevelCurrent, LevelMin);
|
||||||
|
set => SetProperty(LevelCurrent, value, v => LocalSetting.Set(SettingKeys.CultivationAvatarLevelCurrent, v));
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint LevelTarget { get => levelTarget; set => SetProperty(ref levelTarget, value); }
|
public uint LevelTarget
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeys.CultivationAvatarLevelTarget, LevelMax);
|
||||||
|
set => SetProperty(LevelTarget, value, v => LocalSetting.Set(SettingKeys.CultivationAvatarLevelTarget, v));
|
||||||
|
}
|
||||||
|
|
||||||
public static CalculableAvatar From(Avatar source)
|
public static CalculableAvatar From(Avatar source)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Snap.Hutao.Core.Abstraction;
|
using Snap.Hutao.Core.Abstraction;
|
||||||
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Metadata.Avatar;
|
using Snap.Hutao.Model.Metadata.Avatar;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
@@ -18,44 +19,33 @@ namespace Snap.Hutao.Model.Calculable;
|
|||||||
internal sealed class CalculableSkill
|
internal sealed class CalculableSkill
|
||||||
: ObservableObject,
|
: ObservableObject,
|
||||||
ICalculableSkill,
|
ICalculableSkill,
|
||||||
IMappingFrom<CalculableSkill, ProudableSkill>,
|
IMappingFrom<CalculableSkill, ProudableSkill, SkillType>,
|
||||||
IMappingFrom<CalculableSkill, SkillView>
|
IMappingFrom<CalculableSkill, SkillView, SkillType>
|
||||||
{
|
{
|
||||||
private uint levelCurrent;
|
private readonly SkillType type;
|
||||||
private uint levelTarget;
|
|
||||||
|
|
||||||
/// <summary>
|
private CalculableSkill(ProudableSkill skill, SkillType type)
|
||||||
/// 构造一个新的可计算的技能
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="skill">技能</param>
|
|
||||||
private CalculableSkill(ProudableSkill skill)
|
|
||||||
{
|
{
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
GroupId = skill.GroupId;
|
GroupId = skill.GroupId;
|
||||||
LevelMin = 1;
|
LevelMin = 1;
|
||||||
LevelMax = 10; // hard coded 10 here
|
LevelMax = ProudableSkill.GetMaxLevel();
|
||||||
Name = skill.Name;
|
Name = skill.Name;
|
||||||
Icon = SkillIconConverter.IconNameToUri(skill.Icon);
|
Icon = SkillIconConverter.IconNameToUri(skill.Icon);
|
||||||
Quality = QualityType.QUALITY_NONE;
|
Quality = QualityType.QUALITY_NONE;
|
||||||
|
|
||||||
LevelCurrent = LevelMin;
|
|
||||||
LevelTarget = LevelMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private CalculableSkill(SkillView skill, SkillType type)
|
||||||
/// 构造一个新的可计算的技能
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="skill">技能</param>
|
|
||||||
private CalculableSkill(SkillView skill)
|
|
||||||
{
|
{
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
GroupId = skill.GroupId;
|
GroupId = skill.GroupId;
|
||||||
LevelMin = skill.LevelNumber;
|
LevelMin = skill.LevelNumber;
|
||||||
LevelMax = 10; // hard coded 10 here
|
LevelMax = ProudableSkill.GetMaxLevel();
|
||||||
Name = skill.Name;
|
Name = skill.Name;
|
||||||
Icon = skill.Icon;
|
Icon = skill.Icon;
|
||||||
Quality = QualityType.QUALITY_NONE;
|
Quality = QualityType.QUALITY_NONE;
|
||||||
|
|
||||||
LevelCurrent = LevelMin;
|
|
||||||
LevelTarget = LevelMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -77,18 +67,48 @@ internal sealed class CalculableSkill
|
|||||||
public QualityType Quality { get; }
|
public QualityType Quality { get; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint LevelCurrent { get => levelCurrent; set => SetProperty(ref levelCurrent, value); }
|
public uint LevelCurrent
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeyCurrentFromSkillType(type), LevelMin);
|
||||||
|
set => SetProperty(LevelCurrent, value, v => LocalSetting.Set(SettingKeyCurrentFromSkillType(type), v));
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint LevelTarget { get => levelTarget; set => SetProperty(ref levelTarget, value); }
|
public uint LevelTarget
|
||||||
|
|
||||||
public static CalculableSkill From(ProudableSkill source)
|
|
||||||
{
|
{
|
||||||
return new(source);
|
get => LocalSetting.Get(SettingKeyTargetFromSkillType(type), LevelMax);
|
||||||
|
set => SetProperty(LevelTarget, value, v => LocalSetting.Set(SettingKeyTargetFromSkillType(type), v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CalculableSkill From(SkillView source)
|
public static CalculableSkill From(ProudableSkill source, SkillType type)
|
||||||
{
|
{
|
||||||
return new(source);
|
return new(source, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CalculableSkill From(SkillView source, SkillType type)
|
||||||
|
{
|
||||||
|
return new(source, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SettingKeyCurrentFromSkillType(SkillType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
SkillType.A => SettingKeys.CultivationAvatarSkillACurrent,
|
||||||
|
SkillType.E => SettingKeys.CultivationAvatarSkillECurrent,
|
||||||
|
SkillType.Q => SettingKeys.CultivationAvatarSkillQCurrent,
|
||||||
|
_ => throw Must.NeverHappen(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SettingKeyTargetFromSkillType(SkillType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
SkillType.A => SettingKeys.CultivationAvatarSkillATarget,
|
||||||
|
SkillType.E => SettingKeys.CultivationAvatarSkillETarget,
|
||||||
|
SkillType.Q => SettingKeys.CultivationAvatarSkillQTarget,
|
||||||
|
_ => throw Must.NeverHappen(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Snap.Hutao.Core.Abstraction;
|
using Snap.Hutao.Core.Abstraction;
|
||||||
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
using Snap.Hutao.Model.Metadata.Weapon;
|
using Snap.Hutao.Model.Metadata.Weapon;
|
||||||
@@ -77,10 +78,18 @@ internal sealed class CalculableWeapon
|
|||||||
public QualityType Quality { get; }
|
public QualityType Quality { get; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint LevelCurrent { get => levelCurrent; set => SetProperty(ref levelCurrent, value); }
|
public uint LevelCurrent
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeyCurrentFromQualityType(Quality), LevelMin);
|
||||||
|
set => SetProperty(LevelCurrent, value, v => LocalSetting.Set(SettingKeyCurrentFromQualityType(Quality), v));
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint LevelTarget { get => levelTarget; set => SetProperty(ref levelTarget, value); }
|
public uint LevelTarget
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeyTargetFromQualityType(Quality), LevelMax);
|
||||||
|
set => SetProperty(LevelTarget, value, v => LocalSetting.Set(SettingKeyTargetFromQualityType(Quality), v));
|
||||||
|
}
|
||||||
|
|
||||||
public static CalculableWeapon From(Weapon source)
|
public static CalculableWeapon From(Weapon source)
|
||||||
{
|
{
|
||||||
@@ -91,4 +100,18 @@ internal sealed class CalculableWeapon
|
|||||||
{
|
{
|
||||||
return new(source);
|
return new(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string SettingKeyCurrentFromQualityType(QualityType quality)
|
||||||
|
{
|
||||||
|
return quality >= QualityType.QUALITY_BLUE
|
||||||
|
? SettingKeys.CultivationWeapon90LevelCurrent
|
||||||
|
: SettingKeys.CultivationWeapon70LevelCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SettingKeyTargetFromQualityType(QualityType quality)
|
||||||
|
{
|
||||||
|
return quality >= QualityType.QUALITY_BLUE
|
||||||
|
? SettingKeys.CultivationWeapon90LevelTarget
|
||||||
|
: SettingKeys.CultivationWeapon70LevelTarget;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,14 +6,25 @@ namespace Snap.Hutao.Model.Calculable;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可计算物品的源
|
/// 可计算物品的源
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">可计算类型</typeparam>
|
/// <typeparam name="TResult">可计算类型</typeparam>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal interface ICalculableSource<T>
|
internal interface ICalculableSource<TResult>
|
||||||
where T : ICalculable
|
where TResult : ICalculable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换到可计算的对象
|
/// 转换到可计算的对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>可计算物品</returns>
|
/// <returns>可计算物品</returns>
|
||||||
public T ToCalculable();
|
public TResult ToCalculable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal interface ITypedCalculableSource<TResult, T>
|
||||||
|
where TResult : ICalculable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 转换到可计算的对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param">索引</param>
|
||||||
|
/// <returns>可计算物品</returns>
|
||||||
|
public TResult ToCalculable(T param);
|
||||||
|
}
|
||||||
11
src/Snap.Hutao/Snap.Hutao/Model/Calculable/SkillType.cs
Normal file
11
src/Snap.Hutao/Snap.Hutao/Model/Calculable/SkillType.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Model.Calculable;
|
||||||
|
|
||||||
|
internal enum SkillType
|
||||||
|
{
|
||||||
|
A,
|
||||||
|
E,
|
||||||
|
Q,
|
||||||
|
}
|
||||||
@@ -39,7 +39,12 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItem
|
|||||||
/// 最大等级
|
/// 最大等级
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressMessage("", "CA1822")]
|
[SuppressMessage("", "CA1822")]
|
||||||
public uint MaxLevel { get => 90U; }
|
public uint MaxLevel { get => GetMaxLevel(); }
|
||||||
|
|
||||||
|
public static uint GetMaxLevel()
|
||||||
|
{
|
||||||
|
return 90U;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICalculableAvatar ToCalculable()
|
public ICalculableAvatar ToCalculable()
|
||||||
|
|||||||
@@ -8,11 +8,16 @@ namespace Snap.Hutao.Model.Metadata.Avatar;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 技能信息的接口实现
|
/// 技能信息的接口实现
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed partial class ProudableSkill : ICalculableSource<ICalculableSkill>
|
internal sealed partial class ProudableSkill : ITypedCalculableSource<ICalculableSkill, SkillType>
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
public static uint GetMaxLevel()
|
||||||
public ICalculableSkill ToCalculable()
|
|
||||||
{
|
{
|
||||||
return CalculableSkill.From(this);
|
return 10U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ICalculableSkill ToCalculable(SkillType type)
|
||||||
|
{
|
||||||
|
return CalculableSkill.From(this, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2256,6 +2256,51 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 角色目标等级 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewDialogCultivateBatchAvatarLevelTarget {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewDialogCultivateBatchAvatarLevelTarget", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 普通攻击目标等级 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewDialogCultivateBatchSkillATarget {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewDialogCultivateBatchSkillATarget", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 元素战技目标等级 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewDialogCultivateBatchSkillETarget {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewDialogCultivateBatchSkillETarget", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 元素爆发目标等级 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewDialogCultivateBatchSkillQTarget {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewDialogCultivateBatchSkillQTarget", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 武器目标等级 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewDialogCultivateBatchWeaponLevelTarget {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewDialogCultivateBatchWeaponLevelTarget", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 绑定当前用户与角色 的本地化字符串。
|
/// 查找类似 绑定当前用户与角色 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2284,7 +2329,16 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 添加到当前养成计划 的本地化字符串。
|
/// 查找类似 批量添加或更新到当前养成计划 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewDialogCultivatePromotionDeltaBatchTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewDialogCultivatePromotionDeltaBatchTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 添加或更新到当前养成计划 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ViewDialogCultivatePromotionDeltaTitle {
|
internal static string ViewDialogCultivatePromotionDeltaTitle {
|
||||||
get {
|
get {
|
||||||
@@ -2895,6 +2949,15 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 获取培养材料中,请稍候... 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewModelAvatarPropertyBatchCultivateProgressTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewModelAvatarPropertyBatchCultivateProgressTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 当前角色无法计算,请同步信息后再试 的本地化字符串。
|
/// 查找类似 当前角色无法计算,请同步信息后再试 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2967,6 +3030,24 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 操作完成:添加/更新:{0} 个,跳过 {1} 个 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewModelCultivationBatchAddCompletedFormat {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewModelCultivationBatchAddCompletedFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 操作未全部完成:添加/更新:{0} 个,跳过 {1} 个 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewModelCultivationBatchAddIncompletedFormat {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewModelCultivationBatchAddIncompletedFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 已成功添加至当前养成计划 的本地化字符串。
|
/// 查找类似 已成功添加至当前养成计划 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3642,6 +3723,24 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 所有角色与武器 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageAvatarPropertyCalculateAll {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageAvatarPropertyCalculateAll", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 当前角色与武器 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageAvatarPropertyCalculateCurrent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageAvatarPropertyCalculateCurrent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 双暴评分 的本地化字符串。
|
/// 查找类似 双暴评分 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -905,6 +905,21 @@
|
|||||||
<data name="ViewDialogAchievementArchiveImportTitle" xml:space="preserve">
|
<data name="ViewDialogAchievementArchiveImportTitle" xml:space="preserve">
|
||||||
<value>为当前存档导入成就</value>
|
<value>为当前存档导入成就</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchAvatarLevelTarget" xml:space="preserve">
|
||||||
|
<value>角色目标等级</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchSkillATarget" xml:space="preserve">
|
||||||
|
<value>普通攻击目标等级</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchSkillETarget" xml:space="preserve">
|
||||||
|
<value>元素战技目标等级</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchSkillQTarget" xml:space="preserve">
|
||||||
|
<value>元素爆发目标等级</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchWeaponLevelTarget" xml:space="preserve">
|
||||||
|
<value>武器目标等级</value>
|
||||||
|
</data>
|
||||||
<data name="ViewDialogCultivateProjectAttachUid" xml:space="preserve">
|
<data name="ViewDialogCultivateProjectAttachUid" xml:space="preserve">
|
||||||
<value>绑定当前用户与角色</value>
|
<value>绑定当前用户与角色</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -914,8 +929,11 @@
|
|||||||
<data name="ViewDialogCultivateProjectTitle" xml:space="preserve">
|
<data name="ViewDialogCultivateProjectTitle" xml:space="preserve">
|
||||||
<value>创建新的养成计划</value>
|
<value>创建新的养成计划</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewDialogCultivatePromotionDeltaBatchTitle" xml:space="preserve">
|
||||||
|
<value>批量添加或更新到当前养成计划</value>
|
||||||
|
</data>
|
||||||
<data name="ViewDialogCultivatePromotionDeltaTitle" xml:space="preserve">
|
<data name="ViewDialogCultivatePromotionDeltaTitle" xml:space="preserve">
|
||||||
<value>添加到当前养成计划</value>
|
<value>添加或更新到当前养成计划</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ViewDialogDailyNoteNotificationDailyTaskNotify" xml:space="preserve">
|
<data name="ViewDialogDailyNoteNotificationDailyTaskNotify" xml:space="preserve">
|
||||||
<value>每日委托上线提醒</value>
|
<value>每日委托上线提醒</value>
|
||||||
@@ -1118,6 +1136,9 @@
|
|||||||
<data name="ViewModelAchievementRemoveArchiveTitle" xml:space="preserve">
|
<data name="ViewModelAchievementRemoveArchiveTitle" xml:space="preserve">
|
||||||
<value>确定要删除存档 {0} 吗?</value>
|
<value>确定要删除存档 {0} 吗?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewModelAvatarPropertyBatchCultivateProgressTitle" xml:space="preserve">
|
||||||
|
<value>获取培养材料中,请稍候...</value>
|
||||||
|
</data>
|
||||||
<data name="ViewModelAvatarPropertyCalculateWeaponNull" xml:space="preserve">
|
<data name="ViewModelAvatarPropertyCalculateWeaponNull" xml:space="preserve">
|
||||||
<value>当前角色无法计算,请同步信息后再试</value>
|
<value>当前角色无法计算,请同步信息后再试</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1142,6 +1163,12 @@
|
|||||||
<data name="ViewModelCultivationAddWarning" xml:space="preserve">
|
<data name="ViewModelCultivationAddWarning" xml:space="preserve">
|
||||||
<value>养成计划添加失败</value>
|
<value>养成计划添加失败</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewModelCultivationBatchAddCompletedFormat" xml:space="preserve">
|
||||||
|
<value>操作完成:添加/更新:{0} 个,跳过 {1} 个</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewModelCultivationBatchAddIncompletedFormat" xml:space="preserve">
|
||||||
|
<value>操作未全部完成:添加/更新:{0} 个,跳过 {1} 个</value>
|
||||||
|
</data>
|
||||||
<data name="ViewModelCultivationEntryAddSuccess" xml:space="preserve">
|
<data name="ViewModelCultivationEntryAddSuccess" xml:space="preserve">
|
||||||
<value>已成功添加至当前养成计划</value>
|
<value>已成功添加至当前养成计划</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1367,6 +1394,12 @@
|
|||||||
<data name="ViewPageAvatarPropertyArtifactScore" xml:space="preserve">
|
<data name="ViewPageAvatarPropertyArtifactScore" xml:space="preserve">
|
||||||
<value>圣遗物评分</value>
|
<value>圣遗物评分</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageAvatarPropertyCalculateAll" xml:space="preserve">
|
||||||
|
<value>所有角色与武器</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewPageAvatarPropertyCalculateCurrent" xml:space="preserve">
|
||||||
|
<value>当前角色与武器</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageAvatarPropertyCritScore" xml:space="preserve">
|
<data name="ViewPageAvatarPropertyCritScore" xml:space="preserve">
|
||||||
<value>双暴评分</value>
|
<value>双暴评分</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask InsertCultivateEntryAsync(CultivateEntry entry)
|
public async ValueTask AddCultivateEntryAsync(CultivateEntry entry)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -126,7 +126,7 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask InsertCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd)
|
public async ValueTask AddCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -177,14 +177,14 @@ internal sealed partial class CultivationService : ICultivationService
|
|||||||
if (entry is null)
|
if (entry is null)
|
||||||
{
|
{
|
||||||
entry = CultivateEntry.From(Current.InnerId, type, itemId);
|
entry = CultivateEntry.From(Current.InnerId, type, itemId);
|
||||||
await cultivationDbService.InsertCultivateEntryAsync(entry).ConfigureAwait(false);
|
await cultivationDbService.AddCultivateEntryAsync(entry).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Guid entryId = entry.InnerId;
|
Guid entryId = entry.InnerId;
|
||||||
await cultivationDbService.DeleteCultivateItemRangeByEntryIdAsync(entryId).ConfigureAwait(false);
|
await cultivationDbService.DeleteCultivateItemRangeByEntryIdAsync(entryId).ConfigureAwait(false);
|
||||||
|
|
||||||
IEnumerable<CultivateItem> toAdd = items.Select(item => CultivateItem.From(entryId, item));
|
IEnumerable<CultivateItem> toAdd = items.Select(item => CultivateItem.From(entryId, item));
|
||||||
await cultivationDbService.InsertCultivateItemRangeAsync(toAdd).ConfigureAwait(false);
|
await cultivationDbService.AddCultivateItemRangeAsync(toAdd).ConfigureAwait(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ internal interface ICultivationDbService
|
|||||||
|
|
||||||
ValueTask<List<InventoryItem>> GetInventoryItemListByProjectIdAsync(Guid projectId);
|
ValueTask<List<InventoryItem>> GetInventoryItemListByProjectIdAsync(Guid projectId);
|
||||||
|
|
||||||
ValueTask InsertCultivateEntryAsync(CultivateEntry entry);
|
ValueTask AddCultivateEntryAsync(CultivateEntry entry);
|
||||||
|
|
||||||
ValueTask InsertCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd);
|
ValueTask AddCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd);
|
||||||
|
|
||||||
void UpdateCultivateItem(CultivateItem item);
|
void UpdateCultivateItem(CultivateItem item);
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,7 @@
|
|||||||
<None Remove="View\Dialog\AchievementArchiveCreateDialog.xaml" />
|
<None Remove="View\Dialog\AchievementArchiveCreateDialog.xaml" />
|
||||||
<None Remove="View\Dialog\AchievementImportDialog.xaml" />
|
<None Remove="View\Dialog\AchievementImportDialog.xaml" />
|
||||||
<None Remove="View\Dialog\CultivateProjectDialog.xaml" />
|
<None Remove="View\Dialog\CultivateProjectDialog.xaml" />
|
||||||
|
<None Remove="View\Dialog\CultivatePromotionDeltaBatchDialog.xaml" />
|
||||||
<None Remove="View\Dialog\CultivatePromotionDeltaDialog.xaml" />
|
<None Remove="View\Dialog\CultivatePromotionDeltaDialog.xaml" />
|
||||||
<None Remove="View\Dialog\DailyNoteNotificationDialog.xaml" />
|
<None Remove="View\Dialog\DailyNoteNotificationDialog.xaml" />
|
||||||
<None Remove="View\Dialog\GachaLogImportDialog.xaml" />
|
<None Remove="View\Dialog\GachaLogImportDialog.xaml" />
|
||||||
@@ -299,6 +300,12 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="View\Dialog\CultivatePromotionDeltaBatchDialog.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="View\Control\StatisticsSegmented.xaml">
|
<Page Update="View\Control\StatisticsSegmented.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1">
|
<ScrollViewer Grid.Row="1">
|
||||||
<StackPanel Margin="16,0,16,16">
|
<StackPanel Margin="16,0,12,16">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,16,0,8"
|
Margin="0,16,0,8"
|
||||||
Style="{StaticResource BaseTextBlockStyle}"
|
Style="{StaticResource BaseTextBlockStyle}"
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<ContentDialog
|
||||||
|
x:Class="Snap.Hutao.View.Dialog.CultivatePromotionDeltaBatchDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:cwc="using:CommunityToolkit.WinUI.Controls"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||||
|
xmlns:shvd="using:Snap.Hutao.View.Dialog"
|
||||||
|
Title="{shcm:ResourceString Name=ViewDialogCultivatePromotionDeltaBatchTitle}"
|
||||||
|
d:DataContext="{d:DesignInstance shvd:CultivatePromotionDeltaDialog}"
|
||||||
|
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
||||||
|
DefaultButton="Primary"
|
||||||
|
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||||
|
Style="{StaticResource DefaultContentDialogStyle}"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<ContentDialog.Resources>
|
||||||
|
<x:Double x:Key="NumberBoxMinWidth">180</x:Double>
|
||||||
|
|
||||||
|
<x:Double x:Key="SettingsCardSpacing">3</x:Double>
|
||||||
|
<x:Double x:Key="SettingsCardMinHeight">0</x:Double>
|
||||||
|
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
|
||||||
|
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
|
||||||
|
</ContentDialog.Resources>
|
||||||
|
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewDialogCultivateBatchAvatarLevelTarget}">
|
||||||
|
<NumberBox
|
||||||
|
Grid.Column="2"
|
||||||
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Maximum="90"
|
||||||
|
Minimum="1"
|
||||||
|
SpinButtonPlacementMode="Inline"
|
||||||
|
Value="{x:Bind PromotionDelta.AvatarLevelTarget, Mode=TwoWay}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewDialogCultivateBatchSkillATarget}">
|
||||||
|
<NumberBox
|
||||||
|
Grid.Column="2"
|
||||||
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Maximum="10"
|
||||||
|
Minimum="1"
|
||||||
|
SpinButtonPlacementMode="Inline"
|
||||||
|
Value="{x:Bind PromotionDelta.SkillList[0].LevelTarget, Mode=TwoWay}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewDialogCultivateBatchSkillETarget}">
|
||||||
|
<NumberBox
|
||||||
|
Grid.Column="2"
|
||||||
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Maximum="10"
|
||||||
|
Minimum="1"
|
||||||
|
SpinButtonPlacementMode="Inline"
|
||||||
|
Value="{x:Bind PromotionDelta.SkillList[1].LevelTarget, Mode=TwoWay}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewDialogCultivateBatchSkillQTarget}">
|
||||||
|
<NumberBox
|
||||||
|
Grid.Column="2"
|
||||||
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Maximum="10"
|
||||||
|
Minimum="1"
|
||||||
|
SpinButtonPlacementMode="Inline"
|
||||||
|
Value="{x:Bind PromotionDelta.SkillList[2].LevelTarget, Mode=TwoWay}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewDialogCultivateBatchWeaponLevelTarget}">
|
||||||
|
<NumberBox
|
||||||
|
Grid.Column="2"
|
||||||
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Maximum="90"
|
||||||
|
Minimum="1"
|
||||||
|
SpinButtonPlacementMode="Inline"
|
||||||
|
Value="{x:Bind PromotionDelta.Weapon.LevelTarget, Mode=TwoWay}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
</StackPanel>
|
||||||
|
</ContentDialog>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.View.Dialog;
|
||||||
|
|
||||||
|
[DependencyProperty("PromotionDelta", typeof(AvatarPromotionDelta))]
|
||||||
|
internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
||||||
|
{
|
||||||
|
private readonly ITaskContext taskContext;
|
||||||
|
|
||||||
|
public CultivatePromotionDeltaBatchDialog(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
XamlRoot = serviceProvider.GetRequiredService<MainWindow>().Content.XamlRoot;
|
||||||
|
|
||||||
|
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
|
||||||
|
|
||||||
|
PromotionDelta = AvatarPromotionDelta.CreateForBaseline();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<ValueResult<bool, AvatarPromotionDelta>> GetPromotionDeltaBaselineAsync()
|
||||||
|
{
|
||||||
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
|
ContentDialogResult result = await ShowAsync();
|
||||||
|
|
||||||
|
return new(result == ContentDialogResult.Primary, PromotionDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,9 +7,7 @@
|
|||||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||||
xmlns:shvc="using:Snap.Hutao.View.Control"
|
xmlns:shvc="using:Snap.Hutao.View.Control"
|
||||||
xmlns:shvd="using:Snap.Hutao.View.Dialog"
|
|
||||||
Title="{shcm:ResourceString Name=ViewDialogCultivatePromotionDeltaTitle}"
|
Title="{shcm:ResourceString Name=ViewDialogCultivatePromotionDeltaTitle}"
|
||||||
d:DataContext="{d:DesignInstance shvd:CultivatePromotionDeltaDialog}"
|
|
||||||
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
||||||
DefaultButton="Primary"
|
DefaultButton="Primary"
|
||||||
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||||
@@ -27,9 +25,9 @@
|
|||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Margin="0,8,0,0"
|
Margin="0,8,0,0"
|
||||||
Visibility="{Binding Avatar, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
Visibility="{x:Bind Avatar, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
||||||
<Border Style="{StaticResource BorderCardStyle}">
|
<Border Style="{StaticResource BorderCardStyle}">
|
||||||
<Grid Margin="8" DataContext="{Binding Avatar}">
|
<Grid Margin="8" DataContext="{x:Bind Avatar}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
<ColumnDefinition Width="160"/>
|
<ColumnDefinition Width="160"/>
|
||||||
@@ -73,7 +71,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<ItemsControl ItemsSource="{Binding Avatar.Skills}">
|
<ItemsControl ItemsSource="{x:Bind Avatar.Skills}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Border Margin="0,2,0,0" Style="{StaticResource BorderCardStyle}">
|
<Border Margin="0,2,0,0" Style="{StaticResource BorderCardStyle}">
|
||||||
@@ -128,7 +126,7 @@
|
|||||||
Margin="0,8,0,0"
|
Margin="0,8,0,0"
|
||||||
Visibility="{Binding Weapon, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
Visibility="{Binding Weapon, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
||||||
<Border Style="{StaticResource BorderCardStyle}">
|
<Border Style="{StaticResource BorderCardStyle}">
|
||||||
<Grid Margin="8" DataContext="{Binding Weapon}">
|
<Grid Margin="8" DataContext="{x:Bind Weapon}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
<ColumnDefinition Width="160"/>
|
<ColumnDefinition Width="160"/>
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ internal sealed partial class CultivatePromotionDeltaDialog : ContentDialog
|
|||||||
|
|
||||||
Avatar = options.Avatar;
|
Avatar = options.Avatar;
|
||||||
Weapon = options.Weapon;
|
Weapon = options.Weapon;
|
||||||
DataContext = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,19 +52,19 @@ internal sealed partial class CultivatePromotionDeltaDialog : ContentDialog
|
|||||||
AvatarPromotionDelta delta = new()
|
AvatarPromotionDelta delta = new()
|
||||||
{
|
{
|
||||||
AvatarId = Avatar?.AvatarId ?? 0,
|
AvatarId = Avatar?.AvatarId ?? 0,
|
||||||
AvatarLevelCurrent = Avatar?.LevelCurrent ?? 0,
|
AvatarLevelCurrent = Avatar is not null ? Math.Clamp(Avatar.LevelCurrent, Avatar.LevelMin, Avatar.LevelMax) : 0,
|
||||||
AvatarLevelTarget = Avatar?.LevelTarget ?? 0,
|
AvatarLevelTarget = Avatar is not null ? Math.Clamp(Avatar.LevelTarget, Avatar.LevelMin, Avatar.LevelMax) : 0,
|
||||||
SkillList = Avatar?.Skills.SelectList(s => new PromotionDelta()
|
SkillList = Avatar?.Skills.SelectList(skill => new PromotionDelta()
|
||||||
{
|
{
|
||||||
Id = s.GroupId,
|
Id = skill.GroupId,
|
||||||
LevelCurrent = s.LevelCurrent,
|
LevelCurrent = Math.Clamp(skill.LevelCurrent, skill.LevelMin, skill.LevelMax),
|
||||||
LevelTarget = s.LevelTarget,
|
LevelTarget = Math.Clamp(skill.LevelTarget, skill.LevelMin, skill.LevelMax),
|
||||||
}),
|
}),
|
||||||
Weapon = Weapon is null ? null : new PromotionDelta()
|
Weapon = Weapon is null ? null : new PromotionDelta()
|
||||||
{
|
{
|
||||||
Id = Weapon.WeaponId,
|
Id = Weapon.WeaponId,
|
||||||
LevelCurrent = Weapon.LevelCurrent,
|
LevelCurrent = Math.Clamp(Weapon.LevelCurrent, Weapon.LevelMin, Weapon.LevelMax),
|
||||||
LevelTarget = Weapon.LevelTarget,
|
LevelTarget = Math.Clamp(Weapon.LevelTarget, Weapon.LevelMin, Weapon.LevelMax),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -89,11 +89,17 @@
|
|||||||
CommandParameter="{Binding ElementName=ItemsPanelSelector, Path=Current, Converter={StaticResource PanelSelectorModeConverter}}"
|
CommandParameter="{Binding ElementName=ItemsPanelSelector, Path=Current, Converter={StaticResource PanelSelectorModeConverter}}"
|
||||||
Icon="{shcm:FontIcon Glyph=}"
|
Icon="{shcm:FontIcon Glyph=}"
|
||||||
Label="{shcm:ResourceString Name=ViewPageAvatarPropertyExportAsImage}"/>
|
Label="{shcm:ResourceString Name=ViewPageAvatarPropertyExportAsImage}"/>
|
||||||
<AppBarButton
|
<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="{shcm:ResourceString Name=ViewPageCultivateCalculate}">
|
||||||
Command="{Binding CultivateCommand}"
|
<AppBarButton.Flyout>
|
||||||
CommandParameter="{Binding SelectedAvatar}"
|
<MenuFlyout>
|
||||||
Icon="{shcm:FontIcon Glyph=}"
|
<MenuFlyoutItem
|
||||||
Label="{shcm:ResourceString Name=ViewPageCultivateCalculate}"/>
|
Command="{Binding CultivateCommand}"
|
||||||
|
CommandParameter="{Binding SelectedAvatar}"
|
||||||
|
Text="{shcm:ResourceString Name=ViewPageAvatarPropertyCalculateCurrent}"/>
|
||||||
|
<MenuFlyoutItem Command="{Binding BatchCultivateCommand}" Text="{shcm:ResourceString Name=ViewPageAvatarPropertyCalculateAll}"/>
|
||||||
|
</MenuFlyout>
|
||||||
|
</AppBarButton.Flyout>
|
||||||
|
</AppBarButton>
|
||||||
<AppBarSeparator/>
|
<AppBarSeparator/>
|
||||||
<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="{shcm:ResourceString Name=ViewAvatarPropertySyncDataButtonLabel}">
|
<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="{shcm:ResourceString Name=ViewAvatarPropertySyncDataButtonLabel}">
|
||||||
<AppBarButton.Flyout>
|
<AppBarButton.Flyout>
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
private readonly IAvatarInfoService avatarInfoService;
|
private readonly IAvatarInfoService avatarInfoService;
|
||||||
private readonly IClipboardInterop clipboardInterop;
|
private readonly IClipboardInterop clipboardInterop;
|
||||||
private readonly CalculatorClient calculatorClient;
|
private readonly CalculatorClient calculatorClient;
|
||||||
|
private readonly IInfoBarService infoBarService;
|
||||||
private readonly ITaskContext taskContext;
|
private readonly ITaskContext taskContext;
|
||||||
private readonly IUserService userService;
|
private readonly IUserService userService;
|
||||||
private readonly IInfoBarService infoBarService;
|
|
||||||
|
|
||||||
private Summary? summary;
|
private Summary? summary;
|
||||||
private AvatarView? selectedAvatar;
|
private AvatarView? selectedAvatar;
|
||||||
@@ -161,66 +161,168 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
[Command("CultivateCommand")]
|
[Command("CultivateCommand")]
|
||||||
private async Task CultivateAsync(AvatarView? avatar)
|
private async Task CultivateAsync(AvatarView? avatar)
|
||||||
{
|
{
|
||||||
if (avatar is not null)
|
if (avatar is null)
|
||||||
{
|
{
|
||||||
if (userService.Current is not null)
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userService.Current is null)
|
||||||
|
{
|
||||||
|
infoBarService.Warning(SH.MustSelectUserAndUid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (avatar.Weapon is null)
|
||||||
{
|
{
|
||||||
if (avatar.Weapon is null)
|
infoBarService.Warning(SH.ViewModelAvatarPropertyCalculateWeaponNull);
|
||||||
{
|
return;
|
||||||
infoBarService.Warning(SH.ViewModelAvatarPropertyCalculateWeaponNull);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContentDialog must be created by main thread.
|
CalculableOptions options = new(avatar.ToCalculable(), avatar.Weapon.ToCalculable());
|
||||||
CalculableOptions options = new(avatar.ToCalculable(), avatar.Weapon.ToCalculable());
|
CultivatePromotionDeltaDialog dialog = await contentDialogFactory.CreateInstanceAsync<CultivatePromotionDeltaDialog>(options).ConfigureAwait(false);
|
||||||
CultivatePromotionDeltaDialog dialog = await contentDialogFactory.CreateInstanceAsync<CultivatePromotionDeltaDialog>(options).ConfigureAwait(false);
|
(bool isOk, CalculatorAvatarPromotionDelta delta) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
|
||||||
(bool isOk, CalculatorAvatarPromotionDelta delta) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!isOk)
|
if (!isOk)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Response<CalculatorConsumption> consumptionResponse = await calculatorClient
|
Response<CalculatorConsumption> consumptionResponse = await calculatorClient
|
||||||
.ComputeAsync(userService.Current.Entity, delta)
|
.ComputeAsync(userService.Current.Entity, delta)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!consumptionResponse.IsOk())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorConsumption consumption = consumptionResponse.Data;
|
||||||
|
|
||||||
|
List<CalculatorItem> items = CalculatorItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume);
|
||||||
|
bool avatarSaved = await cultivationService
|
||||||
|
.SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// take a hot path if avatar is not saved.
|
||||||
|
bool avatarAndWeaponSaved = avatarSaved && await cultivationService
|
||||||
|
.SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (!consumptionResponse.IsOk())
|
if (avatarAndWeaponSaved)
|
||||||
{
|
{
|
||||||
return;
|
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
CalculatorConsumption consumption = consumptionResponse.Data;
|
|
||||||
|
|
||||||
List<CalculatorItem> items = CalculatorItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume);
|
|
||||||
bool avatarSaved = await cultivationService
|
|
||||||
.SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
// take a hot path if avatar is not saved.
|
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||||
bool avatarAndWeaponSaved = avatarSaved && await cultivationService
|
}
|
||||||
.SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
}
|
||||||
.ConfigureAwait(false);
|
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||||
|
{
|
||||||
|
infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (avatarAndWeaponSaved)
|
[Command("BatchCultivateCommand")]
|
||||||
{
|
private async Task BatchCultivateAsync()
|
||||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
{
|
||||||
}
|
if (summary is { Avatars: { } avatars })
|
||||||
else
|
{
|
||||||
{
|
if (userService.Current is null)
|
||||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
{
|
||||||
}
|
infoBarService.Warning(SH.MustSelectUserAndUid);
|
||||||
}
|
|
||||||
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
|
||||||
{
|
|
||||||
infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
infoBarService.Warning(SH.MustSelectUserAndUid);
|
CultivatePromotionDeltaBatchDialog dialog = await contentDialogFactory.CreateInstanceAsync<CultivatePromotionDeltaBatchDialog>().ConfigureAwait(false);
|
||||||
|
(bool isOk, CalculatorAvatarPromotionDelta baseline) = await dialog.GetPromotionDeltaBaselineAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (isOk)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(baseline.SkillList);
|
||||||
|
ArgumentNullException.ThrowIfNull(baseline.Weapon);
|
||||||
|
|
||||||
|
ContentDialog progressDialog = await contentDialogFactory
|
||||||
|
.CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyBatchCultivateProgressTitle)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
using (await progressDialog.BlockAsync(taskContext).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
BatchCultivateResult result = default;
|
||||||
|
foreach (AvatarView avatar in avatars)
|
||||||
|
{
|
||||||
|
baseline.AvatarId = avatar.Id;
|
||||||
|
baseline.AvatarLevelCurrent = Math.Min(avatar.LevelNumber, baseline.AvatarLevelTarget);
|
||||||
|
baseline.SkillList[0].Id = avatar.Skills[0].GroupId;
|
||||||
|
baseline.SkillList[0].LevelCurrent = Math.Min(avatar.Skills[0].LevelNumber, baseline.SkillList[0].LevelTarget);
|
||||||
|
baseline.SkillList[1].Id = avatar.Skills[1].GroupId;
|
||||||
|
baseline.SkillList[1].LevelCurrent = Math.Min(avatar.Skills[1].LevelNumber, baseline.SkillList[1].LevelTarget);
|
||||||
|
baseline.SkillList[2].Id = avatar.Skills[2].GroupId;
|
||||||
|
baseline.SkillList[2].LevelCurrent = Math.Min(avatar.Skills[2].LevelNumber, baseline.SkillList[2].LevelTarget);
|
||||||
|
|
||||||
|
if (avatar.Weapon is null)
|
||||||
|
{
|
||||||
|
result.SkippedCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseline.Weapon.Id = avatar.Weapon.Id;
|
||||||
|
baseline.Weapon.LevelCurrent = Math.Min(avatar.Weapon.LevelNumber, baseline.Weapon.LevelTarget);
|
||||||
|
|
||||||
|
Response<CalculatorConsumption> consumptionResponse = await calculatorClient
|
||||||
|
.ComputeAsync(userService.Current.Entity, baseline)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!consumptionResponse.IsOk())
|
||||||
|
{
|
||||||
|
result.Interrupted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CalculatorConsumption consumption = consumptionResponse.Data;
|
||||||
|
|
||||||
|
List<CalculatorItem> items = CalculatorItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume);
|
||||||
|
bool avatarSaved = await cultivationService
|
||||||
|
.SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// take a hot path if avatar is not saved.
|
||||||
|
bool avatarAndWeaponSaved = avatarSaved && await cultivationService
|
||||||
|
.SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (avatarAndWeaponSaved)
|
||||||
|
{
|
||||||
|
result.SucceedCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Interrupted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||||
|
{
|
||||||
|
infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Interrupted)
|
||||||
|
{
|
||||||
|
infoBarService.Warning(SH.ViewModelCultivationBatchAddIncompletedFormat.Format(result.SucceedCount, result.SkippedCount));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoBarService.Success(SH.ViewModelCultivationBatchAddCompletedFormat.Format(result.SucceedCount, result.SkippedCount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ internal sealed class AvatarView : INameIconSide, ICalculableSource<ICalculableA
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 武器
|
/// 武器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WeaponView? Weapon { get; set; } = default!;
|
public WeaponView? Weapon { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 圣遗物列表
|
/// 圣遗物列表
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
|
|
||||||
|
internal struct BatchCultivateResult
|
||||||
|
{
|
||||||
|
public int SucceedCount;
|
||||||
|
public int SkippedCount;
|
||||||
|
public bool Interrupted;
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ namespace Snap.Hutao.ViewModel.AvatarProperty;
|
|||||||
/// 天赋
|
/// 天赋
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class SkillView : NameIconDescription, ICalculableSource<ICalculableSkill>
|
internal sealed class SkillView : NameIconDescription, ITypedCalculableSource<ICalculableSkill, SkillType>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 技能属性
|
/// 技能属性
|
||||||
@@ -34,8 +34,8 @@ internal sealed class SkillView : NameIconDescription, ICalculableSource<ICalcul
|
|||||||
internal SkillGroupId GroupId { get; set; }
|
internal SkillGroupId GroupId { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICalculableSkill ToCalculable()
|
public ICalculableSkill ToCalculable(SkillType type)
|
||||||
{
|
{
|
||||||
return CalculableSkill.From(this);
|
return CalculableSkill.From(this, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
|
|
||||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
||||||
@@ -46,4 +47,19 @@ internal sealed class AvatarPromotionDelta
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("weapon")]
|
[JsonPropertyName("weapon")]
|
||||||
public PromotionDelta? Weapon { get; set; }
|
public PromotionDelta? Weapon { get; set; }
|
||||||
|
|
||||||
|
public static AvatarPromotionDelta CreateForBaseline()
|
||||||
|
{
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
AvatarLevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarLevelTarget, 90U),
|
||||||
|
SkillList = new()
|
||||||
|
{
|
||||||
|
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillATarget, 10U), },
|
||||||
|
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillETarget, 10U), },
|
||||||
|
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillQTarget, 10U), },
|
||||||
|
},
|
||||||
|
Weapon = new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationWeapon90LevelTarget, 90U), },
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user