添加 ShopForm 下的 StatForm,展示玩家属性
This commit is contained in:
@@ -10,6 +10,7 @@ namespace SepCore.UI
|
||||
public List<GoodsItemContext> GoodsItems;
|
||||
public DisplayListContext PropListContext;
|
||||
public DisplayListContext WeaponListContext;
|
||||
public StatContext StatContext;
|
||||
|
||||
// 控制字段
|
||||
public bool NeedRefreshGoodsItems;
|
||||
@@ -17,6 +18,7 @@ namespace SepCore.UI
|
||||
public bool NeedRefreshWeaponList;
|
||||
public bool NeedRefreshPropList;
|
||||
public bool NeedRefreshPrice;
|
||||
public bool NeedRefreshStat;
|
||||
|
||||
public ShopContext()
|
||||
{
|
||||
|
||||
@@ -40,14 +40,26 @@ namespace SepCore.UI
|
||||
BuildDisplayListContext(DisplayListAreaType.Prop, rawData.PropItems, rawData.PropMaxCount),
|
||||
WeaponListContext = BuildDisplayListContext(DisplayListAreaType.Weapon, rawData.WeaponItems,
|
||||
rawData.WeaponMaxCount),
|
||||
StatContext = BuildStatContext(rawData.StatRawData),
|
||||
NeedRefreshGoodsItems = true,
|
||||
NeedRefreshPlayerCoin = true,
|
||||
NeedRefreshPropList = true,
|
||||
NeedRefreshWeaponList = true,
|
||||
NeedRefreshStat = true,
|
||||
NeedRefreshPrice = true
|
||||
};
|
||||
}
|
||||
|
||||
private static StatContext BuildStatContext(StatRawData rawData)
|
||||
{
|
||||
if (rawData == null)
|
||||
{
|
||||
Log.Error("ShopController.BuildStatContext: rawData is null.");
|
||||
}
|
||||
|
||||
return new StatContext(rawData);
|
||||
}
|
||||
|
||||
private static DisplayListContext BuildDisplayListContext(DisplayListAreaType listType,
|
||||
IReadOnlyList<object> items, int maxCount)
|
||||
{
|
||||
|
||||
@@ -144,6 +144,12 @@ namespace SepCore.UI
|
||||
Context.NeedRefreshPropList = true;
|
||||
}
|
||||
|
||||
if (result.StatRawData != null)
|
||||
{
|
||||
Context.StatContext = BuildStatContext(result.StatRawData);
|
||||
Context.NeedRefreshStat = true;
|
||||
}
|
||||
|
||||
Context.NeedRefreshGoodsItems = true;
|
||||
RefreshUI(Form, Context);
|
||||
}
|
||||
@@ -243,6 +249,8 @@ namespace SepCore.UI
|
||||
Context.WeaponListContext.CurrentCount = currentCount;
|
||||
|
||||
Context.NeedRefreshWeaponList = true;
|
||||
Context.StatContext = BuildStatContext(_useCase.CreateStatRawData());
|
||||
Context.NeedRefreshStat = true;
|
||||
RefreshUI(Form, Context);
|
||||
GameEntry.UIRouter.CloseUIAsync(UIFormType.ItemTooltipForm).Forget();
|
||||
}
|
||||
|
||||
@@ -49,6 +49,12 @@ namespace SepCore.UI
|
||||
View.weaponList.OnInit(context.WeaponListContext);
|
||||
context.NeedRefreshWeaponList = false;
|
||||
}
|
||||
|
||||
if (context.NeedRefreshStat)
|
||||
{
|
||||
View.statForm.OnInit(context.StatContext);
|
||||
context.NeedRefreshStat = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
|
||||
@@ -16,5 +16,6 @@ namespace SepCore.UI
|
||||
[SerializeField] public global::SepCore.UI.FormatTextUI continueButtonFormatText;
|
||||
[SerializeField] public global::SepCore.UI.DisplayListForm weaponList;
|
||||
[SerializeField] public global::SepCore.UI.DisplayListForm propList;
|
||||
[SerializeField] public global::SepCore.UI.StatForm statForm;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 541f4dba32e55be469dcd6b180b94fdb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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:
|
||||
Reference in New Issue
Block a user