375 lines
13 KiB
C#
375 lines
13 KiB
C#
using System.Collections.Generic;
|
||
using Logic.Multilingual;
|
||
using Logic.Skill;
|
||
using RuntimeData;
|
||
using TH1_Core.Events;
|
||
using TH1_Core.Managers;
|
||
using TH1_Logic.Core;
|
||
using TH1Resource;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TH1_UI.HintUI
|
||
{
|
||
/// <summary>
|
||
/// 英雄介绍信息面板
|
||
/// </summary>
|
||
public class HeroHintPanel : MonoBehaviour
|
||
{
|
||
/// <summary>
|
||
/// 当前是否处于固定状态,固定期间其他 HeroHintPanel 触发器不响应
|
||
/// </summary>
|
||
public static bool IsPinned { get; set; }
|
||
|
||
[Header("关闭按钮")]
|
||
public Button CloseButton;
|
||
public GameObject ClickHint;
|
||
|
||
[Header("Part 1: 等级选择栏")]
|
||
public Button Level1Button;
|
||
public Button Level2Button;
|
||
public Button Level3Button;
|
||
public Button Level4Button;
|
||
|
||
[Header("Part 2: 角色介绍模块")]
|
||
public Image AvatarImage;
|
||
public TextMeshProUGUI SubtitleText; // 英雄称号
|
||
public TextMeshProUGUI TitleText; // 英雄名称
|
||
public TextMeshProUGUI AttackText;
|
||
public TextMeshProUGUI DefenseText;
|
||
public TextMeshProUGUI HealthText;
|
||
public TextMeshProUGUI MoveText;
|
||
public TextMeshProUGUI RangeText;
|
||
public TextMeshProUGUI VisionText;
|
||
public TextMeshProUGUI ActionText;
|
||
|
||
[Header("Part 3: 技能模块")]
|
||
public Transform SkillGridContainer;
|
||
public GameObject SkillCirclePrefab;
|
||
|
||
[Header("Part 4: 能力模块")]
|
||
public Transform AbilityGridContainer;
|
||
|
||
[Header("Part 5: 升级模块")]
|
||
public GameObject UpgradeSection;
|
||
public TextMeshProUGUI UpgradeDescText;
|
||
|
||
[Header("Part 6: 角色描述与台词")]
|
||
public GameObject CharDescSection;
|
||
public TextMeshProUGUI CharDescText;
|
||
public GameObject CharDiagSection;
|
||
public TextMeshProUGUI CharDiagText;
|
||
|
||
private List<HeroHintPanelCommonCircleMono> _skillCircleList = new List<HeroHintPanelCommonCircleMono>();
|
||
private GiantType _currentGiantType;
|
||
private uint _currentLevel;
|
||
private readonly uint MAX_LEVEL = 3; // Lv.4时隐藏升级模块
|
||
|
||
private void Awake()
|
||
{
|
||
InitializeButtons();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化等级按钮事件
|
||
/// </summary>
|
||
private void InitializeButtons()
|
||
{
|
||
Level1Button?.onClick.AddListener(() => SwitchLevel(0));
|
||
Level2Button?.onClick.AddListener(() => SwitchLevel(1));
|
||
Level3Button?.onClick.AddListener(() => SwitchLevel(2));
|
||
Level4Button?.onClick.AddListener(() => SwitchLevel(3));
|
||
|
||
CloseButton?.onClick.AddListener(() =>
|
||
{
|
||
EventManager.Publish(new HideHeroHintPanelEvent { Force = true });
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置英雄信息
|
||
/// </summary>
|
||
public void SetHeroInfo(GiantType giantType, uint initialLevel = 0)
|
||
{
|
||
_currentGiantType = giantType;
|
||
_currentLevel = initialLevel;
|
||
|
||
RefreshPanel();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换等级
|
||
/// </summary>
|
||
private void SwitchLevel(uint level)
|
||
{
|
||
if (_currentLevel == level) return;
|
||
_currentLevel = level;
|
||
RefreshPanel();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新整个面板
|
||
/// </summary>
|
||
private void RefreshPanel()
|
||
{
|
||
UpdateLevelButtons();
|
||
UpdateHeroInfo();
|
||
UpdateCharInfo();
|
||
UpdateSkills();
|
||
UpdateActionArea();
|
||
UpdateUpgradeSection();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新等级按钮状态
|
||
/// </summary>
|
||
private void UpdateLevelButtons()
|
||
{
|
||
SetButtonSelected(Level1Button, _currentLevel == 0);
|
||
SetButtonSelected(Level2Button, _currentLevel == 1);
|
||
SetButtonSelected(Level3Button, _currentLevel == 2);
|
||
SetButtonSelected(Level4Button, _currentLevel == 3);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置按钮选中状态
|
||
/// </summary>
|
||
private void SetButtonSelected(Button button, bool selected)
|
||
{
|
||
if (button == null) return;
|
||
var targetColor = selected ? new Color(1f, 0.65f, 0f) : Color.white;
|
||
var colors = button.colors;
|
||
colors.normalColor = targetColor;
|
||
colors.highlightedColor = targetColor;
|
||
colors.selectedColor = targetColor;
|
||
button.colors = colors;
|
||
// 强制刷新按钮底图颜色,避免状态机未回到 Normal 时看不到变化
|
||
var img = button.targetGraphic as Image;
|
||
if (img != null) img.color = targetColor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新英雄角色介绍信息
|
||
/// </summary>
|
||
private void UpdateHeroInfo()
|
||
{
|
||
var unitFullType = new UnitFullType(UnitType.Giant, _currentGiantType, _currentLevel);
|
||
|
||
// 从 UnitTypeDataAssets 获取数据
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitFullType, out var unitTypeInfo))
|
||
return;
|
||
|
||
// 获取英雄头像
|
||
if (Table.Instance.UnitTypeDataAssets.GetUnitSpriteByGiantType(_currentGiantType, out var avatarSprite))
|
||
AvatarImage.sprite = avatarSprite;
|
||
|
||
// 设置称号和名称
|
||
MultilingualManager.Instance.SetUIText(SubtitleText, ""); // TODO: 称号需要从其他配置获取
|
||
MultilingualManager.Instance.SetUIText(TitleText, unitTypeInfo.Name);
|
||
|
||
// 设置属性文本
|
||
AttackText.text = unitTypeInfo.Attack.ToString();
|
||
DefenseText.text = unitTypeInfo.Defense.ToString();
|
||
HealthText.text = unitTypeInfo.MaxHealth.ToString();
|
||
MoveText.text = unitTypeInfo.MoveRange.ToString();
|
||
RangeText.text = unitTypeInfo.AttackRange.ToString();
|
||
VisionText.text = unitTypeInfo.Skills != null && unitTypeInfo.Skills.Contains(SkillType.SCOUT) ? "2" : "1";
|
||
// ActionText 保持 prefab 默认文本,不做覆盖
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新角色描述与台词(从 LibraryDataAssets 读取,与等级无关)
|
||
/// </summary>
|
||
private void UpdateCharInfo()
|
||
{
|
||
if (!Table.Instance.LibraryDataAssets.GetLibraryInfoByGiant(_currentGiantType, out var libraryData))
|
||
{
|
||
if (CharDescSection != null) CharDescSection.SetActive(false);
|
||
if (CharDiagSection != null) CharDiagSection.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
// 角色描述
|
||
if (CharDescSection != null && CharDescText != null)
|
||
{
|
||
CharDescSection.SetActive(true);
|
||
MultilingualManager.Instance.SetUIText(CharDescText, libraryData.Desc);
|
||
}
|
||
|
||
// 角色台词
|
||
if (CharDiagSection != null && CharDiagText != null)
|
||
{
|
||
CharDiagSection.SetActive(true);
|
||
var diagStr = MultilingualManager.Instance.GetMultilingualTextSafe(libraryData.Diag);
|
||
CharDiagText.text = $"\u201C{diagStr}\u201D";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新技能模块
|
||
/// </summary>
|
||
private void UpdateSkills()
|
||
{
|
||
var unitFullType = new UnitFullType(UnitType.Giant, _currentGiantType, _currentLevel);
|
||
|
||
// 获取单位技能列表
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitFullType, out var unitTypeInfo))
|
||
{
|
||
HideAllSkillCircles();
|
||
return;
|
||
}
|
||
|
||
var skillList = unitTypeInfo.Skills;
|
||
if (skillList == null || skillList.Count == 0)
|
||
{
|
||
HideAllSkillCircles();
|
||
return;
|
||
}
|
||
|
||
// 过滤:只保留 ViewType 不是 Normal 且不是 Special 的技能
|
||
var filteredSkills = new List<SkillType>();
|
||
foreach (var skill in skillList)
|
||
{
|
||
if (Table.Instance.SkillDataAssets.GetSkillInfo(skill, out var sInfo))
|
||
{
|
||
if (sInfo.SkillViewType != SkillViewType.Normal && sInfo.SkillViewType != SkillViewType.Special)
|
||
filteredSkills.Add(skill);
|
||
}
|
||
}
|
||
|
||
if (filteredSkills.Count == 0)
|
||
{
|
||
HideAllSkillCircles();
|
||
return;
|
||
}
|
||
|
||
// 确保有足够数量的 SkillCircle
|
||
while (_skillCircleList.Count < filteredSkills.Count)
|
||
{
|
||
var go = Instantiate(SkillCirclePrefab, SkillGridContainer);
|
||
var circleMono = go.GetComponent<HeroHintPanelCommonCircleMono>();
|
||
if (circleMono == null)
|
||
circleMono = go.AddComponent<HeroHintPanelCommonCircleMono>();
|
||
_skillCircleList.Add(circleMono);
|
||
}
|
||
|
||
// 设置每个技能圆圈的内容
|
||
for (int i = 0; i < _skillCircleList.Count; i++)
|
||
{
|
||
if (i < filteredSkills.Count)
|
||
{
|
||
_skillCircleList[i].gameObject.SetActive(true);
|
||
_skillCircleList[i].SetContent(filteredSkills[i], unitFullType);
|
||
}
|
||
else
|
||
{
|
||
_skillCircleList[i].gameObject.SetActive(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新能力(Action)模块的显隐
|
||
/// </summary>
|
||
private void UpdateActionArea()
|
||
{
|
||
if (AbilityGridContainer == null) return;
|
||
|
||
var unitFullType = new UnitFullType(UnitType.Giant, _currentGiantType, _currentLevel);
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitFullType, out var unitTypeInfo)
|
||
|| !unitTypeInfo.EnableAction
|
||
|| unitTypeInfo.EnableActions == null
|
||
|| unitTypeInfo.EnableActions.Count == 0)
|
||
{
|
||
AbilityGridContainer.gameObject.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
AbilityGridContainer.gameObject.SetActive(true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏所有技能圆圈
|
||
/// </summary>
|
||
private void HideAllSkillCircles()
|
||
{
|
||
foreach (var circle in _skillCircleList)
|
||
{
|
||
circle.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新升级模块
|
||
/// </summary>
|
||
private void UpdateUpgradeSection()
|
||
{
|
||
// Lv.4 隐藏升级模块
|
||
if (_currentLevel >= MAX_LEVEL)
|
||
{
|
||
UpgradeSection?.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
UpgradeSection?.SetActive(true);
|
||
|
||
// 从 HeroDataAssets 获取任务数据
|
||
if (!Table.Instance.HeroDataAssets.GetHeroInfo(_currentGiantType, out var heroInfo))
|
||
{
|
||
UpgradeDescText.text = "";
|
||
return;
|
||
}
|
||
|
||
// 获取对应等级的升级任务描述 (Lv.1-Lv.3 对应 TaskList 的 0-2)
|
||
int taskIndex = (int)_currentLevel;
|
||
if (heroInfo.TaskList != null && taskIndex < heroInfo.TaskList.Count)
|
||
{
|
||
var taskInfo = heroInfo.TaskList[taskIndex];
|
||
// 构建参数列表:param1=当前进度, param2=目标值, param3=技能名
|
||
var param1 = "0";
|
||
var param2 = taskInfo.Param.ToString();
|
||
var param3 = "";
|
||
if (taskInfo.SkillParam != SkillType.NONE &&
|
||
Table.Instance.SkillDataAssets.GetSkillInfo(taskInfo.SkillParam, out var skillInfo))
|
||
{
|
||
param3 = MultilingualManager.Instance.GetMultilingualTextSafe(skillInfo.SkillName);
|
||
}
|
||
else if (!string.IsNullOrEmpty(taskInfo.SkillName))
|
||
{
|
||
param3 = MultilingualManager.Instance.GetMultilingualTextSafe(taskInfo.SkillName);
|
||
}
|
||
MultilingualManager.Instance.SetUIText(UpgradeDescText, taskInfo.Desc,
|
||
new List<string> { param1, param2, param3 });
|
||
}
|
||
else
|
||
{
|
||
UpgradeDescText.text = "";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据固定状态切换 CloseButton / ClickHint 的显隐
|
||
/// </summary>
|
||
public void UpdatePinState(bool pinned)
|
||
{
|
||
if (CloseButton != null) CloseButton.gameObject.SetActive(pinned);
|
||
if (ClickHint != null) ClickHint.SetActive(!pinned);
|
||
// hover 预览时不拦截射线,避免遮住 trigger 导致闪烁;pinned 后才允许交互
|
||
var cg = GetComponent<CanvasGroup>();
|
||
if (cg != null) cg.blocksRaycasts = pinned;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空面板
|
||
/// </summary>
|
||
public void Clear()
|
||
{
|
||
_currentGiantType = GiantType.None;
|
||
_currentLevel = 0;
|
||
HideAllSkillCircles();
|
||
UpgradeSection?.SetActive(false);
|
||
}
|
||
}
|
||
}
|