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}");
}
}
}