using System.Collections.Generic; using System.Text; using SepCore.Definition; using SepCore.Entity; using UnityGameFramework.Runtime; namespace SepCore.CustomUtility { public static class ItemDescUtility { private static readonly string[] _statTypeNames = { "无效", // None = 0 "最大生命", // MaxHp = 1 "生命恢复", // HpRegen = 2 "生命窃取", // LifeSteal = 3 "伤害加成", // DamagePercent = 4 "近战伤害", // MeleeDamage = 5 "远程伤害", // RangedDamage = 6 "元素伤害", // ElementalDamage = 7 "攻击速度", // AttackSpeed = 8 "暴击率", // CritChance = 9 "工程学", // Engineering = 10 "攻击范围", // Range = 11 "护甲", // Armor = 12 "闪避率", // Dodge = 13 "移动速度", // MoveSpeed = 14 "收获", // Harvesting = 15 "幸运" // Luck = 16 }; public static string Describe(StatModifierConfig statModifierConfig) { if (statModifierConfig == null) { return string.Empty; } int index = (int)statModifierConfig.StatType; string name = (index >= 0 && index < _statTypeNames.Length) ? _statTypeNames[index] : statModifierConfig.StatType.ToString(); string colorTag = statModifierConfig.Value >= 0 ? "green" : "red"; string sign = statModifierConfig.Value >= 0 ? "+" : ""; StatConfig statConfig = null; if (GameEntry.Luban != null && GameEntry.Luban.IsReady) { statConfig = GameEntry.Luban.Get(index); } if (statConfig != null && !string.IsNullOrEmpty(statConfig.Name)) { name = statConfig.Name; } // 是否以百分比展示:由 StatConfig.IsPercentDisplay 真正驱动(Luban 未就绪时 fallback 到已知百分比属性) bool isPercentDisplay = statConfig != null ? statConfig.IsPercentDisplay : (statModifierConfig.StatType is StatType.DamagePercent or StatType.AttackSpeed or StatType.CritChance or StatType.Dodge); // 1. 修饰类型判断 bool isPercentAdd = statModifierConfig.ModifierType == ModifierType.PercentAdd; bool isPercentMult = statModifierConfig.ModifierType == ModifierType.PercentMult; bool isFlat = statModifierConfig.ModifierType == ModifierType.Flat; // 2. UI 百分比展示裁决: // - 任意属性的 PercentAdd 词条属于比例加成(如 攻速 +19%、伤害 +5%、移速 +15%) // - 或属性自身在配置表中标记为百分比显示(IsPercentDisplay 为 true,如暴击率、闪避率等),其 Flat 加成应以百分比呈现(如 0.1 -> +10%) bool shouldDisplayAsPercent = isPercentAdd || (isFlat && isPercentDisplay); if (shouldDisplayAsPercent) { float displayPercent = statModifierConfig.Value * 100f; return $"{name}: {sign}{displayPercent:0.##}%"; } if (isPercentMult) { return $"{name}: x{statModifierConfig.Value:0.##}"; } return $"{name}: {sign}{statModifierConfig.Value:0.##}"; } public static string CreatePropDescription(IEnumerable modifiers) { if (modifiers == null) { return null; } StringBuilder sb = new StringBuilder(); foreach (StatModifierConfig modifier in modifiers) { sb.Append(Describe(modifier)); sb.Append('\n'); } return sb.ToString(); } public static string CreateWeaponDescription(WeaponConfig weaponConfig) { return CreateWeaponDescription(weaponConfig.Attack, weaponConfig.Cooldown, weaponConfig.AttackRange, weaponConfig.StatModifierConfigs); } public static string CreateWeaponDescription(WeaponData weaponData) { if (weaponData == null) { Log.Error("Weapon data is invalid."); return string.Empty; } return CreateWeaponDescription(weaponData.Attack, weaponData.Cooldown, weaponData.AttackRange, weaponData.Modifiers); } public static string CreatePropDescription(PropItem prop) { if (prop == null) { Log.Error("Prop is invalid."); return string.Empty; } return CreatePropDescription(prop.Modifiers); } public static string CreateWeaponDescription(int attack, float cooldown, float attackRange, IEnumerable modifiers = null) { float baseCrit = GameEntry.Luban.Global.WeaponBaseCrit; float critMult = GameEntry.Luban.Global.CritMultiplier; StringBuilder sb = new StringBuilder(); sb.AppendLine($"伤害: {attack}"); sb.AppendLine($"暴击: x{critMult:0.##} ({baseCrit * 100:0.##}%)"); sb.AppendLine($"冷却: {cooldown:0.##}s"); sb.AppendLine($"范围: {attackRange:0.##}"); string modifiersDesc = CreatePropDescription(modifiers); if (!string.IsNullOrEmpty(modifiersDesc)) { sb.AppendLine(); sb.Append(modifiersDesc.TrimEnd()); } return sb.ToString().TrimEnd(); } } }