添加 ShopForm 下的 StatForm,展示玩家属性

This commit is contained in:
2026-09-25 00:03:39 +08:00
parent c61eb7fb68
commit 051c075183
29 changed files with 6574 additions and 51 deletions
@@ -0,0 +1,92 @@
using System.Collections.Generic;
using SepCore.Definition;
using UnityEngine;
namespace SepCore.UI
{
public class StatContext : UIContext
{
public StatRawData RawData { get; }
public Dictionary<StatType, string> FormattedValues { get; } = new Dictionary<StatType, string>();
public StatContext()
{
}
public StatContext(StatRawData rawData)
{
RawData = rawData;
if (rawData != null)
{
foreach (KeyValuePair<StatType, float> pair in rawData.Values)
{
FormattedValues[pair.Key] = FormatStatValue(pair.Key, pair.Value);
}
}
}
public string GetFormattedValue(StatType statType)
{
return FormattedValues.TryGetValue(statType, out string text) ? text : string.Empty;
}
public void SetFormattedValue(StatType statType, string text)
{
FormattedValues[statType] = text;
}
public static string FormatStatValue(StatType statType, float value)
{
StatConfig config = (GameEntry.Luban != null && GameEntry.Luban.IsReady)
? GameEntry.Luban.Get<StatConfig>((int)statType)
: null;
float baseValue = config?.DefaultBaseValue ?? (statType is StatType.DamagePercent or StatType.AttackSpeed ? 1f : 0f);
bool isPercent = config?.IsPercentDisplay ?? (statType is StatType.DamagePercent or StatType.AttackSpeed or StatType.CritChance or StatType.Dodge or StatType.LifeSteal);
string colorTag = null;
if (value > baseValue + 1e-4f)
{
colorTag = "green";
}
else if (value < baseValue - 1e-4f)
{
colorTag = "red";
}
string text;
if (statType is StatType.DamagePercent or StatType.AttackSpeed)
{
// 增伤与攻速基准为 1.0(即 0% 加成)。面板显示相对基准的增量,如 0%、+5%、-10%
float bonusPercent = (value - 1f) * 100f;
string sign = bonusPercent > 0 ? "+" : "";
text = $"{sign}{bonusPercent:0.##}%";
}
else if (isPercent || statType == StatType.LifeSteal)
{
// 概率/比率属性(暴击率、闪避率、生命窃取):以百分比形式呈现
float displayPercent = value * 100f;
string sign = (value > baseValue && baseValue != 0) ? "+" : "";
text = $"{sign}{displayPercent:0.##}%";
}
else
{
if (Mathf.Approximately(value, Mathf.Round(value)))
{
text = Mathf.RoundToInt(value).ToString();
}
else
{
text = value.ToString("0.##");
}
}
if (!string.IsNullOrEmpty(colorTag))
{
return $"<color={colorTag}>{text}</color>";
}
return text;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4bca40033be046a49a3c1a253af9d6a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,38 @@
using SepCore.Definition;
namespace SepCore.UI
{
public partial class StatForm
{
public void OnInit(StatContext context)
{
RefreshUI(context);
}
public void RefreshUI(StatContext context)
{
if (context == null)
{
UnityGameFramework.Runtime.Log.Error("StatForm.RefreshUI: context is null.");
return;
}
View.maxHpValue.text = context.GetFormattedValue(StatType.MaxHp);
View.hpRegenValue.text = context.GetFormattedValue(StatType.HpRegen);
View.lifeStealValue.text = context.GetFormattedValue(StatType.LifeSteal);
View.damagePercentValue.text = context.GetFormattedValue(StatType.DamagePercent);
View.meleeDamageValue.text = context.GetFormattedValue(StatType.MeleeDamage);
View.rangedDamageValue.text = context.GetFormattedValue(StatType.RangedDamage);
View.elementalDamageValue.text = context.GetFormattedValue(StatType.ElementalDamage);
View.attackSpeedValue.text = context.GetFormattedValue(StatType.AttackSpeed);
View.critChanceValue.text = context.GetFormattedValue(StatType.CritChance);
View.engineeringValue.text = context.GetFormattedValue(StatType.Engineering);
View.rangeValue.text = context.GetFormattedValue(StatType.Range);
View.armorValue.text = context.GetFormattedValue(StatType.Armor);
View.dodgeValue.text = context.GetFormattedValue(StatType.Dodge);
View.moveSpeedValue.text = context.GetFormattedValue(StatType.MoveSpeed);
View.harvestingValue.text = context.GetFormattedValue(StatType.Harvesting);
View.luckValue.text = context.GetFormattedValue(StatType.Luck);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a6aaf8b66f78da4a93a47566847e736
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,13 @@
// <auto-generated />
using UnityEngine;
namespace SepCore.UI
{
[DisallowMultipleComponent]
public partial class StatForm : UGuiForm
{
[SerializeField] private StatView _view = null;
public StatView View => _view;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e561792b1190bde4ba98bdc92b608801
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,26 @@
// <auto-generated />
using UnityEngine;
namespace SepCore.UI
{
[DisallowMultipleComponent]
public partial class StatView : MonoBehaviour
{
[SerializeField] public global::TMPro.TextMeshProUGUI maxHpValue;
[SerializeField] public global::TMPro.TextMeshProUGUI hpRegenValue;
[SerializeField] public global::TMPro.TextMeshProUGUI lifeStealValue;
[SerializeField] public global::TMPro.TextMeshProUGUI damagePercentValue;
[SerializeField] public global::TMPro.TextMeshProUGUI meleeDamageValue;
[SerializeField] public global::TMPro.TextMeshProUGUI rangedDamageValue;
[SerializeField] public global::TMPro.TextMeshProUGUI elementalDamageValue;
[SerializeField] public global::TMPro.TextMeshProUGUI attackSpeedValue;
[SerializeField] public global::TMPro.TextMeshProUGUI critChanceValue;
[SerializeField] public global::TMPro.TextMeshProUGUI engineeringValue;
[SerializeField] public global::TMPro.TextMeshProUGUI rangeValue;
[SerializeField] public global::TMPro.TextMeshProUGUI armorValue;
[SerializeField] public global::TMPro.TextMeshProUGUI dodgeValue;
[SerializeField] public global::TMPro.TextMeshProUGUI moveSpeedValue;
[SerializeField] public global::TMPro.TextMeshProUGUI harvestingValue;
[SerializeField] public global::TMPro.TextMeshProUGUI luckValue;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cfe0c98c2edc3244e982e2492aaa2edc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: