TH1/Unity/Assets/Scripts/TH1_Renderer/UnitStatusArea.cs
2026-03-17 15:54:42 +08:00

331 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using Logic.Skill;
using RuntimeData;
using TH1Resource;
using UnityEngine;
using UnityEngine.UI;
namespace TH1_Renderer
{
/// <summary>
/// 单位负面状态图标数据类 - 存储单个状态的显示信息和对应的GameObject
/// </summary>
[Serializable]
public class UnitStatusIcon
{
/// <summary>对应的技能类型</summary>
public SkillType SkillType { get; private set; }
/// <summary>技能等级/层数</summary>
public int Level { get; private set; }
/// <summary>显示用的GameObject</summary>
public GameObject IconObject { get; private set; }
/// <summary>图标Image组件</summary>
public Image IconImage { get; private set; }
/// <summary>层数文本组件(可选)</summary>
public TMPro.TextMeshProUGUI LevelText { get; private set; }
/// <summary>是否需要显示层数</summary>
public bool HasLevelDisplay => LevelText != null;
public UnitStatusIcon(SkillType skillType, int level, GameObject iconObject)
{
SkillType = skillType;
Level = level;
IconObject = iconObject;
// 获取组件引用
IconImage = iconObject.GetComponent<Image>();
LevelText = iconObject.GetComponentInChildren<TMPro.TextMeshProUGUI>();
}
/// <summary>
/// 更新层数显示
/// </summary>
public void UpdateLevel(int newLevel)
{
Level = newLevel;
if (HasLevelDisplay && Level > 1)
{
LevelText.text = Level.ToString();
LevelText.gameObject.SetActive(true);
}
else if (HasLevelDisplay)
{
LevelText.gameObject.SetActive(false);
}
}
/// <summary>
/// 设置图标Sprite
/// </summary>
public void SetIcon(Sprite sprite)
{
if (IconImage != null)
IconImage.sprite = sprite;
}
/// <summary>
/// 设置图标颜色
/// </summary>
public void SetColor(Color color)
{
if (IconImage != null)
IconImage.color = color;
}
/// <summary>
/// 销毁图标GameObject
/// </summary>
public void Destroy()
{
if (IconObject != null)
GameObject.Destroy(IconObject);
}
/// <summary>
/// 设置显示状态
/// </summary>
public void SetVisible(bool visible)
{
if (IconObject != null)
IconObject.SetActive(visible);
}
}
/// <summary>
/// 单位状态管理器 - 管理单位的所有重要负面状态显示
/// </summary>
public class UnitStatusArea
{
private readonly Dictionary<SkillType, UnitStatusIcon> _statusIcons = new();
private readonly Transform _statusContainer;
private readonly GameObject _statusIconPrefab;
private readonly uint _unitId;
// KomeijiFear 图片路径RuntimeResources 下相对路径)
private const string KOMEIJI_FEAR_PATH = "TH1UI/Icon/SkillIcon/Komeiji/Skill_KomeijiFear";
private const string KOMEIJI_FEAR2_PATH = "TH1UI/Icon/SkillIcon/Komeiji/Skill_KomeijiFear2";
/// <summary>
/// 当前显示的状态数量
/// </summary>
public int Count => _statusIcons.Count;
/// <summary>
/// 获取所有当前显示的状态
/// </summary>
public IEnumerable<UnitStatusIcon> AllIcons => _statusIcons.Values;
public UnitStatusArea(uint unitId, Transform statusContainer, GameObject statusIconPrefab)
{
_unitId = unitId;
_statusContainer = statusContainer;
_statusIconPrefab = statusIconPrefab;
}
/// <summary>
/// 添加或更新状态显示
/// </summary>
/// <param name="skillType">技能类型</param>
/// <param name="level">技能等级/层数</param>
/// <param name="icon">图标Sprite</param>
/// <returns>是否成功添加或更新</returns>
public bool AddOrUpdateStatus(SkillType skillType, int level, Sprite icon)
{
bool isUpdate = false;
Sprite finalIcon = icon;
// KomeijiFear 特殊处理:根据等级切换图片
if (skillType == SkillType.KomeijiFear)
{
string targetPath = level >= 2 ? KOMEIJI_FEAR2_PATH : KOMEIJI_FEAR_PATH;
var specialSprite = Resources.Load<Sprite>(targetPath);
if (specialSprite != null)
finalIcon = specialSprite;
}
if (_statusIcons.TryGetValue(skillType, out var existingIcon))
{
// 已存在则更新层数和图标
existingIcon.UpdateLevel(level);
// KomeijiFear 等级变化可能导致图片变化
if (skillType == SkillType.KomeijiFear && finalIcon != existingIcon.IconImage?.sprite)
{
existingIcon.SetIcon(finalIcon);
}
isUpdate = true;
}
else
{
// 不存在则创建新的
if (_statusIconPrefab == null || _statusContainer == null)
return false;
var newIconObj = GameObject.Instantiate(_statusIconPrefab, _statusContainer);
var statusIcon = new UnitStatusIcon(skillType, level, newIconObj);
statusIcon.SetIcon(finalIcon);
statusIcon.UpdateLevel(level);
// KomeijiFear 特殊处理:显示为绿色
if (skillType == SkillType.KomeijiFear)
{
statusIcon.SetColor(Color.green);
}
else
{
statusIcon.SetColor(Color.white);
}
_statusIcons.Add(skillType, statusIcon);
isUpdate = true;
}
// 每次更新后强制刷新布局
RefreshLayout();
return isUpdate;
}
/// <summary>
/// 移除指定状态
/// </summary>
/// <param name="skillType">技能类型</param>
/// <returns>是否成功移除</returns>
public bool RemoveStatus(SkillType skillType)
{
if (!_statusIcons.TryGetValue(skillType, out var icon))
return false;
icon.Destroy();
_statusIcons.Remove(skillType);
// 移除后强制刷新布局
RefreshLayout();
return true;
}
/// <summary>
/// 检查是否包含指定状态
/// </summary>
public bool HasStatus(SkillType skillType)
{
return _statusIcons.ContainsKey(skillType);
}
/// <summary>
/// 获取指定状态的层数
/// </summary>
public int GetStatusLevel(SkillType skillType)
{
return _statusIcons.TryGetValue(skillType, out var icon) ? icon.Level : 0;
}
/// <summary>
/// 清除所有状态
/// </summary>
public void ClearAllStatus()
{
foreach (var icon in _statusIcons.Values)
{
icon.Destroy();
}
_statusIcons.Clear();
// 清除后强制刷新布局
RefreshLayout();
}
/// <summary>
/// 同步单位的技能数据 - 只显示指定的负面技能
/// </summary>
/// <param name="unitData">单位数据</param>
/// <param name="negativeSkillTypes">需要显示的负面技能类型列表</param>
public void SyncWithUnitSkills(UnitData unitData, List<SkillType> negativeSkillTypes)
{
if (unitData == null || unitData.Skills == null) return;
// 找出需要移除的状态(已不在要显示的列表中)
var toRemove = new List<SkillType>();
foreach (var skillType in _statusIcons.Keys)
{
if (!negativeSkillTypes.Contains(skillType))
toRemove.Add(skillType);
}
bool hasChanged = false;
// 移除过期状态
foreach (var skillType in toRemove)
{
RemoveStatus(skillType);
hasChanged = true;
}
// 更新或添加状态
foreach (var skillType in negativeSkillTypes)
{
if (!unitData.GetSkill(skillType, out var skill))
{
// 如果单位没有此技能但正在显示,则移除
if (HasStatus(skillType))
{
RemoveStatus(skillType);
hasChanged = true;
}
continue;
}
// 获取技能图标
if (!Table.Instance.SkillDataAssets.GetSkillInfo(skillType, out var skillInfo))
continue;
int level = skill.HasLevel ? skill.Level : 1;
// 检查是否需要更新(新增或层数变化)
if (!HasStatus(skillType) || GetStatusLevel(skillType) != level)
{
AddOrUpdateStatus(skillType, level, skillInfo.SkillIcon);
hasChanged = true;
}
}
// 如果有变化强制刷新布局AddOrUpdateStatus 和 RemoveStatus 内部也会调用,这里作为保险)
if (hasChanged)
{
RefreshLayout();
}
}
/// <summary>
/// 刷新所有状态的显示位置(用于自动布局更新)
/// </summary>
public void RefreshLayout()
{
if (_statusContainer == null) return;
// 强制刷新布局
if (_statusContainer is UnityEngine.RectTransform rectTransform)
{
UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
}
}
/// <summary>
/// 设置整个状态区域是否可见
/// </summary>
public void SetAreaVisible(bool visible)
{
if (_statusContainer != null)
_statusContainer.gameObject.SetActive(visible);
}
}
}