using System.Collections.Generic; using System.Text.RegularExpressions; using Cielonos.MainGame.Characters; using UnityEngine; namespace Cielonos.MainGame.UI { /// /// 通用展示文本解析器。 /// 负责将文本中的 {key} 命名占位符替换为运行时动态值, /// 并提供各类游戏数据的展示值计算方法。 /// public static class DisplayTextResolver { private static readonly Regex PlaceholderPattern = new Regex(@"\{(\w+)\}", RegexOptions.Compiled); // ================================================================ // 核心:占位符替换 // ================================================================ /// /// 将文本中的 {key} 占位符替换为 args 字典中对应的值。 /// 未匹配到的占位符保留原样。 /// public static string Resolve(string text, Dictionary args) { if (string.IsNullOrEmpty(text) || args == null || args.Count == 0) return text; return PlaceholderPattern.Replace(text, match => { string key = match.Groups[1].Value; return args.TryGetValue(key, out string value) ? value : match.Value; }); } // ================================================================ // 伤害相关 // ================================================================ /// /// 计算 AttackUnit 的面板展示伤害值。 /// 仅包含攻击者侧倍率,不含随机偏差和受击者侧减伤。 /// public static float ComputeDisplayDamage(AttackUnit unit, CharacterBase attacker) { if (unit == null || unit.isInvalidAttack) return 0f; float damage = unit.startDamage; if (attacker == null) return damage; damage *= attacker.attributeSm[CharacterAttribute.AttackDamageMultiplier]; string typeKey = unit.type.AttackTypeToString() + "DamageDealtMultiplier"; damage *= attacker.attributeSm[typeKey]; damage *= attacker.attributeSm[CharacterAttribute.FinalDamageDealtMultiplier]; return damage; } /// /// 计算 AttackUnit 的面板展示暴击率(含玩家属性加成),结果范围 [0, 1]。 /// public static float ComputeDisplayCriticalChance(AttackUnit unit, CharacterBase attacker) { if (unit == null || unit.isInvalidAttack) return 0f; float chance = unit.criticalChance; if (attacker != null) chance += attacker.attributeSm[CharacterAttribute.CriticalAttackProbability]; return Mathf.Clamp01(chance); } /// /// 计算 AttackUnit 的面板展示暴击伤害倍率(含玩家属性加成)。 /// public static float ComputeDisplayCriticalMultiplier(AttackUnit unit, CharacterBase attacker) { if (unit == null || unit.isInvalidAttack) return 0f; float multiplier = unit.criticalMultiplier; if (attacker != null) multiplier += attacker.attributeSm[CharacterAttribute.CriticalAttackDamageAmplifier]; return multiplier; } /// /// 批量填充指定 AttackUnit 的伤害、暴击率、暴击倍率到 args 字典中。 /// 生成的 key 格式:{prefix}_damage, {prefix}_crit_chance, {prefix}_crit_multiplier。 /// public static void PopulateAttackArgs( Dictionary args, string prefix, AttackUnit unit, CharacterBase attacker) { if (unit == null || unit.isInvalidAttack) return; args[$"{prefix}_damage"] = FormatInt(ComputeDisplayDamage(unit, attacker)); args[$"{prefix}_crit_chance"] = FormatPercent(ComputeDisplayCriticalChance(unit, attacker)); args[$"{prefix}_crit_multiplier"] = FormatFloat(ComputeDisplayCriticalMultiplier(unit, attacker)); } // ================================================================ // 资源花费相关 // ================================================================ /// /// 计算经过能量花费减少属性调整后的展示能量花费。 /// public static float ComputeDisplayEnergyCost(float baseCost, CharacterBase character) { if (character == null) return baseCost; float reduction = character.attributeSm[CharacterAttribute.EnergyCostReduction]; return Mathf.Max(0f, baseCost * (1f - reduction)); } // ================================================================ // 格式化工具 // ================================================================ /// /// 将浮点数格式化为整数字符串(四舍五入)。 /// public static string FormatInt(float value) { return Mathf.RoundToInt(value).ToString(); } /// /// 将浮点数格式化为百分比字符串(如 0.15 → "15%")。 /// public static string FormatPercent(float value) { return $"{Mathf.RoundToInt(value * 100f)}%"; } /// /// 将浮点数格式化为保留指定小数位的字符串。 /// public static string FormatFloat(float value, int decimals = 1) { return value.ToString($"F{decimals}"); } } }