use metadata reliquary affix weight

This commit is contained in:
Lightczx
2023-06-08 20:37:01 +08:00
parent e663c2f353
commit 126e866a02
13 changed files with 71 additions and 1138 deletions

View File

@@ -1,133 +0,0 @@
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace Snap.Hutao.SourceGeneration.Reliquary;
[Generator(LanguageNames.CSharp)]
internal sealed class ReliquaryWeightConfigurationGenerator : IIncrementalGenerator
{
private const string FileName = "ReliquaryWeightConfiguration.json";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
IncrementalValueProvider<ImmutableArray<AdditionalText>> provider = context.AdditionalTextsProvider.Where(MatchFileName).Collect();
context.RegisterSourceOutput(provider, GenerateReliquaryWeightConfiguration);
}
private static bool MatchFileName(AdditionalText text)
{
return Path.GetFileName(text.Path) == FileName;
}
private static void GenerateReliquaryWeightConfiguration(SourceProductionContext context, ImmutableArray<AdditionalText> texts)
{
AdditionalText jsonFile = texts.Single();
string configurationJson = jsonFile.GetText(context.CancellationToken)!.ToString();
Dictionary<string, ReliquaryWeightConfigurationMetadata> metadataMap =
configurationJson.FromJson<Dictionary<string, ReliquaryWeightConfigurationMetadata>>()!;
StringBuilder sourceBuilder = new StringBuilder().Append($$"""
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.AvatarInfo.Factory;
/// <summary>
/// 圣遗物评分权重配置
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{nameof(ReliquaryWeightConfigurationGenerator)}}","1.0.0.0")]
internal static class ReliquaryWeightConfiguration
{
/// <summary>
/// 默认
/// </summary>
public static readonly AffixWeight Default = new(0, 100, 75, 0, 100, 100, 0, 55, 0);
/// <summary>
/// 词条权重
/// </summary>
public static readonly List<AffixWeight> AffixWeights = new()
{
""");
foreach (KeyValuePair<string, ReliquaryWeightConfigurationMetadata> kvp in metadataMap.OrderBy(kvp => kvp.Key))
{
AppendAffixWeight(sourceBuilder, kvp.Key, kvp.Value);
}
sourceBuilder.Append($$"""
};
}
""");
context.AddSource("ReliquaryWeightConfiguration.g.cs", sourceBuilder.ToString());
}
private static void AppendAffixWeight(StringBuilder builder, string id, ReliquaryWeightConfigurationMetadata metadata)
{
StringBuilder lineBuilder = new StringBuilder()
.Append(" new AffixWeight(").Append(id).Append(',')
.Append(' ').Append(metadata.Hp).Append(',')
.Append(' ').Append(metadata.Attack).Append(',')
.Append(' ').Append(metadata.Defense).Append(',')
.Append(' ').Append(metadata.CritRate).Append(',')
.Append(' ').Append(metadata.CritHurt).Append(',')
.Append(' ').Append(metadata.Mastery).Append(',')
.Append(' ').Append(metadata.Recharge).Append(',')
.Append(' ').Append(metadata.Healing).Append(')')
.Append('.').Append(metadata.ElementType).Append("(").Append(metadata.ElementHurt).Append(')');
if (metadata.PhysicialHurt != 0)
{
lineBuilder.Append(".Physical(").Append(metadata.PhysicialHurt).Append(')');
}
lineBuilder.Append(',');
builder.AppendLine(lineBuilder.ToString());
}
private sealed class ReliquaryWeightConfigurationMetadata
{
[DataMember(Name = "hp")]
public int Hp { get; set; }
[DataMember(Name = "atk")]
public int Attack { get; set; }
[DataMember(Name = "def")]
public int Defense { get; set; }
[DataMember(Name = "cpct")]
public int CritRate { get; set; }
[DataMember(Name = "cdmg")]
public int CritHurt { get; set; }
[DataMember(Name = "mastery")]
public int Mastery { get; set; }
[DataMember(Name = "recharge")]
public int Recharge { get; set; }
[DataMember(Name = "heal")]
public int Healing { get; set; }
[DataMember(Name = "element")]
public string ElementType { get; set; } = default!;
[DataMember(Name = "dmg")]
public int ElementHurt { get; set; }
[DataMember(Name = "phy")]
public int PhysicialHurt { get; set; }
}
}

View File

@@ -11,6 +11,29 @@ namespace Snap.Hutao.Model.Metadata.Reliquary;
/// </summary>
internal sealed class ReliquaryAffixWeight
{
private static ReliquaryAffixWeight? defaultValue;
/// <summary>
/// 默认权重
/// </summary>
public static ReliquaryAffixWeight Default
{
get
{
return defaultValue ??= new()
{
HpPercent = 0,
AttackPercent = 75,
DefensePercent = 0,
Critical = 100,
CriticalHurt = 100,
ElementMastery = 0,
ChargeEfficiency = 55,
HealAdd = 0,
};
}
}
/// <summary>
/// 角色 Id
/// </summary>

View File

@@ -1,820 +0,0 @@
{
"10000066": {
"hp": 50,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Hydro"
},
"10000058": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Electro"
},
"10000063": {
"hp": 0,
"atk": 100,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Cryo"
},
"10000064": {
"hp": 0,
"atk": 75,
"def": 100,
"cpct": 80,
"cdmg": 80,
"mastery": 0,
"dmg": 80,
"phy": 0,
"recharge": 80,
"heal": 0,
"element": "Geo"
},
"10000057": {
"hp": 0,
"atk": 50,
"def": 100,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Geo"
},
"10000055": {
"hp": 0,
"atk": 75,
"def": 100,
"cpct": 50,
"cdmg": 50,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 0,
"element": "Geo"
},
"10000032": {
"hp": 100,
"atk": 50,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 80,
"phy": 0,
"recharge": 55,
"heal": 100,
"element": "Pyro"
},
"10000047": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 100,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Anemo"
},
"10000025": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 0,
"element": "Hydro"
},
"10000030": {
"hp": 80,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 50,
"recharge": 55,
"heal": 0,
"element": "Geo"
},
"10000002": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Cryo"
},
"10000023": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Pyro"
},
"10000046": {
"hp": 80,
"atk": 50,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 0,
"heal": 0,
"element": "Pyro"
},
"10000022": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Anemo"
},
"10000054": {
"hp": 100,
"atk": 50,
"def": 0,
"cpct": 0,
"cdmg": 0,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 100,
"element": "Hydro"
},
"10000041": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 0,
"element": "Hydro"
},
"10000038": {
"hp": 0,
"atk": 0,
"def": 100,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 0,
"heal": 0,
"element": "Geo"
},
"10000039": {
"hp": 100,
"atk": 50,
"def": 0,
"cpct": 50,
"cdmg": 50,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 90,
"heal": 100,
"element": "Cryo"
},
"10000051": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 40,
"phy": 100,
"recharge": 55,
"heal": 0,
"element": "Cryo"
},
"10000033": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Hydro"
},
"10000026": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Anemo"
},
"10000049": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 0,
"heal": 0,
"element": "Pyro"
},
"10000056": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Electro"
},
"10000003": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 100,
"recharge": 55,
"heal": 100,
"element": "Anemo"
},
"10000031": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 60,
"recharge": 0,
"heal": 0,
"element": "Electro"
},
"10000045": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 70,
"phy": 80,
"recharge": 30,
"heal": 0,
"element": "Cryo"
},
"10000029": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Pyro"
},
"10000027": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Geo"
},
"10000024": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Electro"
},
"10000042": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 100,
"recharge": 0,
"heal": 0,
"element": "Electro"
},
"10000050": {
"hp": 90,
"atk": 55,
"def": 0,
"cpct": 90,
"cdmg": 90,
"mastery": 75,
"dmg": 90,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Pyro"
},
"10000016": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 0,
"heal": 0,
"element": "Pyro"
},
"10000034": {
"hp": 0,
"atk": 50,
"def": 90,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 70,
"heal": 0,
"element": "Geo"
},
"10000036": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Cryo"
},
"10000035": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 100,
"recharge": 55,
"heal": 100,
"element": "Cryo"
},
"10000015": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 100,
"recharge": 30,
"heal": 0,
"element": "Cryo"
},
"10000048": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Pyro"
},
"10000053": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 100,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 100,
"element": "Anemo"
},
"10000021": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 100,
"recharge": 0,
"heal": 0,
"element": "Pyro"
},
"10000006": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 0,
"heal": 0,
"element": "Electro"
},
"10000062": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 0,
"heal": 0,
"element": "Cryo"
},
"10000044": {
"hp": 0,
"atk": 75,
"def": 75,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 100,
"recharge": 0,
"heal": 0,
"element": "Pyro"
},
"10000043": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 100,
"dmg": 75,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Anemo"
},
"10000020": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 100,
"recharge": 0,
"heal": 0,
"element": "Electro"
},
"10000060": {
"hp": 80,
"atk": 0,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Hydro"
},
"10000065": {
"hp": 100,
"atk": 50,
"def": 0,
"cpct": 50,
"cdmg": 50,
"mastery": 100,
"dmg": 75,
"phy": 0,
"recharge": 55,
"heal": 100,
"element": "Electro"
},
"10000059": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Anemo"
},
"10000069": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 90,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Dendro"
},
"10000067": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Dendro"
},
"10000071": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Electro"
},
"10000072": {
"hp": 75,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Hydro"
},
"10000070": {
"hp": 100,
"atk": 0,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 80,
"dmg": 100,
"phy": 0,
"recharge": 30,
"heal": 0,
"element": "Hydro"
},
"10000073": {
"hp": 0,
"atk": 55,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 100,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Dendro"
},
"10000068": {
"hp": 75,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 75,
"phy": 0,
"recharge": 55,
"heal": 100,
"element": "Electro"
},
"10000074": {
"hp": 100,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 35,
"element": "Cryo"
},
"10000075": {
"hp": 0,
"atk": 80,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 35,
"heal": 0,
"element": "Anemo"
},
"10000076": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 0,
"element": "Anemo"
},
"10000077": {
"hp": 100,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 100,
"element": "Dendro"
},
"10000078": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 100,
"dmg": 100,
"phy": 0,
"recharge": 35,
"heal": 0,
"element": "Dendro"
},
"10000079": {
"hp": 75,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 100,
"dmg": 100,
"phy": 0,
"recharge": 55,
"heal": 0,
"element": "Pyro"
},
"10000080": {
"hp": 75,
"atk": 55,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 0,
"dmg": 75,
"phy": 75,
"recharge": 55,
"heal": 100,
"element": "Cryo"
},
"10000082": {
"hp": 100,
"atk": 0,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 100,
"element": "Dendro"
},
"10000081": {
"hp": 0,
"atk": 75,
"def": 0,
"cpct": 100,
"cdmg": 100,
"mastery": 75,
"dmg": 100,
"phy": 0,
"recharge": 75,
"heal": 0,
"element": "Dendro"
}
}

View File

@@ -1,150 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Service.AvatarInfo.Factory;
/// <summary>
/// 词条权重
/// </summary>
[HighQuality]
internal sealed class AffixWeight : Dictionary<FightProperty, float>
{
/// <summary>
/// 构造一个新的词条权重
/// </summary>
/// <param name="avatarId">角色Id</param>
/// <param name="hp">大生命</param>
/// <param name="atk">大攻击</param>
/// <param name="def">大防御</param>
/// <param name="crit">暴击率</param>
/// <param name="critHurt">暴击伤害</param>
/// <param name="mastery">元素精通</param>
/// <param name="charge">充能效率</param>
/// <param name="heal">治疗加成</param>
/// <param name="name">名称</param>
public AffixWeight(
uint avatarId,
float hp,
float atk,
float def,
float crit,
float critHurt,
float mastery,
float charge,
float heal,
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] = crit;
this[FightProperty.FIGHT_PROP_CRITICAL_HURT] = critHurt;
this[FightProperty.FIGHT_PROP_ELEMENT_MASTERY] = mastery;
this[FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY] = charge;
this[FightProperty.FIGHT_PROP_HEAL_ADD] = heal;
}
/// <summary>
/// 角色Id
/// </summary>
public AvatarId AvatarId { get; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; }
/// <summary>
/// 风元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Anemo(float value = 100)
{
this[FightProperty.FIGHT_PROP_WIND_ADD_HURT] = value;
return this;
}
/// <summary>
/// 冰元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Cryo(float value = 100)
{
this[FightProperty.FIGHT_PROP_ICE_ADD_HURT] = value;
return this;
}
/// <summary>
/// 草元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Dendro(float value = 100)
{
this[FightProperty.FIGHT_PROP_GRASS_ADD_HURT] = value;
return this;
}
/// <summary>
/// 雷元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Electro(float value = 100)
{
this[FightProperty.FIGHT_PROP_ELEC_ADD_HURT] = value;
return this;
}
/// <summary>
/// 岩元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Geo(float value = 100)
{
this[FightProperty.FIGHT_PROP_ROCK_ADD_HURT] = value;
return this;
}
/// <summary>
/// 水元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Hydro(float value = 100)
{
this[FightProperty.FIGHT_PROP_WATER_ADD_HURT] = value;
return this;
}
/// <summary>
/// 火元素伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Pyro(float value = 100)
{
this[FightProperty.FIGHT_PROP_FIRE_ADD_HURT] = value;
return this;
}
/// <summary>
/// 物理伤害伤害加成
/// </summary>
/// <param name="value">值</param>
/// <returns>链式调用对象</returns>
public AffixWeight Physical(float value = 100)
{
this[FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT] = value;
return this;
}
}

View File

@@ -58,10 +58,10 @@ internal sealed class SummaryAvatarFactory
Skills = SummaryHelper.CreateSkills(avatarInfo.SkillLevelMap, avatarInfo.ProudSkillExtraLevelMap, avatar.SkillDepot.CompositeSkillsNoInherents()),
// webinfo part
FetterLevel = avatarInfo.FetterInfo?.ExpLevel ?? 0,
FetterLevel = avatarInfo.FetterInfo?.ExpLevel ?? 0U,
Properties = SummaryAvatarProperties.Create(avatarInfo.FightPropMap),
CritScore = $"{SummaryHelper.ScoreCrit(avatarInfo.FightPropMap):F2}",
LevelNumber = avatarInfo.PropMap?[PlayerProperty.PROP_LEVEL].Value ?? 0,
LevelNumber = avatarInfo.PropMap?[PlayerProperty.PROP_LEVEL].Value ?? 0U,
// processed webinfo part
Weapon = reliquaryAndWeapon.Weapon,

View File

@@ -25,7 +25,8 @@ internal sealed partial class SummaryFactory : ISummaryFactory
{
IdAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false),
IdWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false),
IdRelicMainPropMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false),
IdReliquaryAffixWeightMap = await metadataService.GetIdToReliquaryAffixWeightMapAsync(token).ConfigureAwait(false),
IdReliquaryMainAffixMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false),
IdReliquarySubAffixMap = await metadataService.GetIdToReliquarySubAffixMapAsync(token).ConfigureAwait(false),
ReliqueryLevels = await metadataService.GetReliquaryLevelsAsync(token).ConfigureAwait(false),
Reliquaries = await metadataService.GetReliquariesAsync(token).ConfigureAwait(false),

View File

@@ -26,10 +26,15 @@ internal sealed class SummaryMetadataContext
/// </summary>
public Dictionary<WeaponId, MetadataWeapon> IdWeaponMap { get; set; } = default!;
/// <summary>
/// 权重映射
/// </summary>
public Dictionary<AvatarId, ReliquaryAffixWeight> IdReliquaryAffixWeightMap { get; set; } = default!;
/// <summary>
/// 圣遗物主属性映射
/// </summary>
public Dictionary<ReliquaryMainAffixId, FightProperty> IdRelicMainPropMap { get; set; } = default!;
public Dictionary<ReliquaryMainAffixId, FightProperty> IdReliquaryMainAffixMap { get; set; } = default!;
/// <summary>
/// 圣遗物副属性映射

View File

@@ -10,9 +10,7 @@ using Snap.Hutao.ViewModel.AvatarProperty;
using Snap.Hutao.Web.Enka.Model;
using System.Runtime.InteropServices;
using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary;
using MetadataReliquaryAffix = Snap.Hutao.Model.Metadata.Reliquary.ReliquarySubAffix;
using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
using PropertyReliquary = Snap.Hutao.ViewModel.AvatarProperty.ReliquaryView;
namespace Snap.Hutao.Service.AvatarInfo.Factory;
@@ -43,14 +41,14 @@ internal sealed class SummaryReliquaryFactory
/// 构造圣遗物
/// </summary>
/// <returns>圣遗物</returns>
public PropertyReliquary CreateReliquary()
public ReliquaryView CreateReliquary()
{
MetadataReliquary reliquary = metadataContext.Reliquaries.Single(r => r.Ids.Contains(equip.ItemId));
List<ReliquarySubProperty> subProperty = equip.Reliquary!.AppendPropIdList.EmptyIfNull().SelectList(CreateSubProperty);
int affixCount = GetSecondaryAffixCount(reliquary);
PropertyReliquary result = new()
ReliquaryView result = new()
{
// NameIconDescription
Name = reliquary.Name,
@@ -69,7 +67,7 @@ internal sealed class SummaryReliquaryFactory
result.SecondarySubProperties = new(span[^affixCount..].ToArray());
result.ComposedSubProperties = equip.Flat.ReliquarySubstats!.SelectList(CreateComposedSubProperty);
ReliquaryMainAffixLevel relicLevel = metadataContext.ReliqueryLevels.Single(r => r.Level == equip.Reliquary!.Level && r.Rank == reliquary.RankLevel);
FightProperty property = metadataContext.IdRelicMainPropMap[equip.Reliquary.MainPropId];
FightProperty property = metadataContext.IdReliquaryMainAffixMap[equip.Reliquary.MainPropId];
result.MainProperty = FightPropertyFormat.ToNameValue(property, relicLevel.PropertyMap[property]);
result.Score = ScoreReliquary(property, reliquary, relicLevel, subProperty);
@@ -115,13 +113,18 @@ internal sealed class SummaryReliquaryFactory
{
// 沙 杯 头
// equip.Flat.EquipType is EquipType.EQUIP_SHOES or EquipType.EQUIP_RING or EquipType.EQUIP_DRESS
if ((int)equip.Flat.EquipType > 3)
if (equip.Flat.EquipType > EquipType.EQUIP_SHOES)
{
AffixWeight weightConfig = GetAffixWeightForAvatarId();
ReliquaryAffixWeight affixWeight = metadataContext.IdReliquaryAffixWeightMap.GetValueOrDefault(avatarInfo.AvatarId, ReliquaryAffixWeight.Default);
ReliquaryMainAffixLevel maxRelicLevel = metadataContext.ReliqueryLevels.Where(r => r.Rank == reliquary.RankLevel).MaxBy(r => r.Level)!;
if (property == FightProperty.FIGHT_PROP_ELEC_ADD_HURT)
{
System.Diagnostics.Debugger.Break();
}
float percent = relicLevel.PropertyMap[property] / maxRelicLevel.PropertyMap[property];
float baseScore = 8 * percent * weightConfig.GetValueOrDefault(property);
float baseScore = 8 * percent * affixWeight[property];
float score = subProperties.Sum(p => p.Score);
return ((score + baseScore) / 1700) * 66;
@@ -133,11 +136,6 @@ internal sealed class SummaryReliquaryFactory
}
}
private AffixWeight GetAffixWeightForAvatarId()
{
return ReliquaryWeightConfiguration.AffixWeights.FirstOrDefault(w => w.AvatarId == avatarInfo.AvatarId, ReliquaryWeightConfiguration.Default);
}
private ReliquarySubProperty CreateComposedSubProperty(ReliquarySubstat substat)
{
FormatMethod method = substat.AppendPropId.GetFormatMethod();
@@ -154,7 +152,7 @@ internal sealed class SummaryReliquaryFactory
[SuppressMessage("", "SH002")]
private ReliquarySubProperty CreateSubProperty(ReliquarySubAffixId appendPropId)
{
MetadataReliquaryAffix affix = metadataContext.IdReliquarySubAffixMap[appendPropId];
ReliquarySubAffix affix = metadataContext.IdReliquarySubAffixMap[appendPropId];
FightProperty property = affix.Type;
return new(
@@ -165,10 +163,10 @@ internal sealed class SummaryReliquaryFactory
private float ScoreSubAffix(in ReliquarySubAffixId appendId)
{
MetadataReliquaryAffix affix = metadataContext.IdReliquarySubAffixMap[appendId];
ReliquarySubAffix affix = metadataContext.IdReliquarySubAffixMap[appendId];
AffixWeight weightConfig = GetAffixWeightForAvatarId();
float weight = weightConfig.GetValueOrDefault(affix.Type) / 100F;
ReliquaryAffixWeight affixWeight = metadataContext.IdReliquaryAffixWeightMap.GetValueOrDefault(avatarInfo.AvatarId, ReliquaryAffixWeight.Default);
float weight = affixWeight[affix.Type] / 100F;
// 小字词条,转换到等效百分比计算
if (affix.Type is FightProperty.FIGHT_PROP_HP or FightProperty.FIGHT_PROP_ATTACK or FightProperty.FIGHT_PROP_DEFENSE)
@@ -177,10 +175,10 @@ internal sealed class SummaryReliquaryFactory
float equalPercent = affix.Value / avatarInfo.FightPropMap[affix.Type - 1];
// 获取对应百分比词条权重
weight = weightConfig.GetValueOrDefault(affix.Type + 1) / 100F;
weight = affixWeight[affix.Type + 1] / 100F;
// 最大同属性百分比数值 最大同属性百分比Id 第四五位是战斗属性位
MetadataReliquaryAffix maxPercentAffix = metadataContext.IdReliquarySubAffixMap[SummaryHelper.GetAffixMaxId(appendId + 10U)];
ReliquarySubAffix maxPercentAffix = metadataContext.IdReliquarySubAffixMap[SummaryHelper.GetAffixMaxId(appendId + 10U)];
float equalScore = equalPercent / maxPercentAffix.Value;
return weight * equalScore * 100;

View File

@@ -156,7 +156,7 @@ internal interface IMetadataService : ICastableService
/// </summary>
/// <param name="token">取消令牌</param>
/// <returns>显示与材料映射</returns>
ValueTask<Dictionary<MaterialId, DisplayItem>> GetIdToDisplayAndMaterialMapAsync(CancellationToken token = default);
ValueTask<Dictionary<MaterialId, DisplayItem>> GetIdToDisplayItemAndMaterialMapAsync(CancellationToken token = default);
/// <summary>
/// 异步获取Id到材料的字典
@@ -165,6 +165,13 @@ internal interface IMetadataService : ICastableService
/// <returns>Id到材料的字典</returns>
ValueTask<Dictionary<MaterialId, Material>> GetIdToMaterialMapAsync(CancellationToken token = default(CancellationToken));
/// <summary>
/// 异步获取Id到圣遗物权重的映射
/// </summary>
/// <param name="token">取消令牌</param>
/// <returns>Id到圣遗物权重的字典</returns>
ValueTask<Dictionary<AvatarId, ReliquaryAffixWeight>> GetIdToReliquaryAffixWeightMapAsync(CancellationToken token = default);
/// <summary>
/// 异步获取ID到圣遗物副词条的字典
/// </summary>

View File

@@ -37,7 +37,7 @@ internal sealed partial class MetadataService
}
/// <inheritdoc/>
public async ValueTask<Dictionary<MaterialId, DisplayItem>> GetIdToDisplayAndMaterialMapAsync(CancellationToken token = default)
public async ValueTask<Dictionary<MaterialId, DisplayItem>> GetIdToDisplayItemAndMaterialMapAsync(CancellationToken token = default)
{
string cacheKey = $"{nameof(MetadataService)}.Cache.DisplayAndMaterial.Map.{typeof(MaterialId).Name}";
@@ -66,6 +66,12 @@ internal sealed partial class MetadataService
return FromCacheAsDictionaryAsync<MaterialId, Material>(FileNameMaterial, a => a.Id, token);
}
/// <inheritdoc/>
public ValueTask<Dictionary<AvatarId, ReliquaryAffixWeight>> GetIdToReliquaryAffixWeightMapAsync(CancellationToken token = default)
{
return FromCacheAsDictionaryAsync<AvatarId, ReliquaryAffixWeight>(FileNameReliquaryAffixWeight, r => r.AvatarId, token);
}
/// <inheritdoc/>
public ValueTask<Dictionary<ReliquarySubAffixId, ReliquarySubAffix>> GetIdToReliquarySubAffixMapAsync(CancellationToken token = default)
{

View File

@@ -50,13 +50,11 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
return;
}
ValueStopwatch stopwatch = ValueStopwatch.StartNew();
logger.LogInformation("Metadata initialization begin");
using (ValueStopwatch.MeasureExecution(logger))
{
isInitialized = await TryUpdateMetadataAsync(token).ConfigureAwait(false);
initializeCompletionSource.TrySetResult();
logger.LogInformation("Metadata initialization completed in {time}ms", stopwatch.GetElapsedTime().TotalMilliseconds);
}
}
private async Task<bool> TryUpdateMetadataAsync(CancellationToken token)

View File

@@ -77,7 +77,6 @@
<None Remove="LaunchGameWindow.xaml" />
<None Remove="NativeMethods.json" />
<None Remove="NativeMethods.txt" />
<None Remove="ReliquaryWeightConfiguration.json" />
<None Remove="Resource\Font\CascadiaMono.ttf" />
<None Remove="Resource\Font\MiSans-Regular.ttf" />
<None Remove="Resource\HutaoIconSourceTransparentBackgroundGradient1.png" />
@@ -166,7 +165,6 @@
<AdditionalFiles Include="IdentityStructs.json" />
<AdditionalFiles Include="NativeMethods.json" />
<AdditionalFiles Include="NativeMethods.txt" />
<AdditionalFiles Include="ReliquaryWeightConfiguration.json" />
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>

View File

@@ -58,7 +58,7 @@ internal sealed partial class WikiMonsterViewModel : Abstraction.ViewModel
levelMonsterCurveMap = await metadataService.GetLevelToMonsterCurveMapAsync().ConfigureAwait(false);
List<Monster> monsters = await metadataService.GetMonstersAsync().ConfigureAwait(false);
Dictionary<MaterialId, DisplayItem> idDisplayMap = await metadataService.GetIdToDisplayAndMaterialMapAsync().ConfigureAwait(false);
Dictionary<MaterialId, DisplayItem> idDisplayMap = await metadataService.GetIdToDisplayItemAndMaterialMapAsync().ConfigureAwait(false);
foreach (Monster monster in monsters)
{
monster.DropsView ??= monster.Drops?.SelectList(i => idDisplayMap.GetValueOrDefault(i)!);