TH1/Unity/Assets/Scripts/TH1_UI/View/Info/UIInfoTechTreeView.cs
2026-06-23 04:38:32 +08:00

307 lines
9.2 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 Animancer;
using Logic;
using Logic.Action;
using Logic.Audio;
using Logic.CrashSight;
using Logic.Multilingual;
using Logic.Skill;
using RuntimeData;
using TH1_Core.Events;
using TH1_Logic.Core;
using TH1_Logic.MatchConfig;
using TH1_UI.Components;
using TH1_UI.HintUI;
using TH1Resource;
using TMPro;
using UI.HintUI;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
//用于匹配科技树视觉位置的enum标记
public enum TechTreeCircleViewType { t1,t2,t3,t4,t5,t11,t12,t21,t22,t31,t32,t41,t42,t51,t52,t110,t120,t210,t220,t310,t320,t410,t420,t510,t520,t0 }
namespace TH1_UI.View.Info
{
public class UIInfoTechTreeView : Base.View
{
public Button closeButton;
public ViDelegateAssisstant.Dele OnBtnCloseClick;
[System.Serializable]
public class TechTreeCirclePair
{
public TechTreeCircleViewType ViewType;
public UIInfoTechTreeCircleMono CircleMono;
}
[Header("头像相关")]
public TextMeshProUGUI TechPoint;
public Image LeaderAvatar;
public TextMeshProUGUI ForceName;
public GameObject MountainPoint;
public TextMeshProUGUI MountainCount;
public GameObject VikingPoint;
public TextMeshProUGUI VikingCount;
private bool _showVikingPoint;
[Header("TreeCircle相关")]
public List< TechTreeCirclePair > TechTreeCircleMonoList;
private CivEnum _showCivEnum = CivEnum.Common;
private ForceEnum _showForceEnum = ForceEnum.Common;
[Header("TreeLine相关")]
public List<UIInfoTechTreeViewTypeMono> treeLineList;
public Color TreeLineColorYellow;
public Color TreeLineColorGray;
public Color TreeLineColorWhite;
[Header("T0相关")]
public GameObject T0Hint;
[Header("子窗口CheckPanel相关")]
public UIInfoTechTreeCheckPanelMono CheckPanel;
protected override void OnInit()
{
base.OnInit();
closeButton.onClick.RemoveAllListeners();
closeButton.onClick.AddListener(() => { OnBtnCloseClick.Invoke(); });
CheckPanel.InitStart(RefreshStatus);
EnsureVikingCountDynamicText();
}
public bool InitAllTechCircle()
{
//Step #1 获得当前player和playerInfo
var viewPlayer = Main.MapData.PlayerMap.SelfPlayerData;
if (viewPlayer == null || !Table.Instance.PlayerDataAssets.GetPlayerInfo(viewPlayer, out var playerInfo))
{
LogSystem.LogError("UIInfoTechTreeView.InitAllTechCircle(): viewPlayer or playerInfo is null");
return false;
}
//Step #2
foreach (var tech in playerInfo.TechPool)
{
if (!Table.Instance.TechDataAssets.GetTechInfo(tech, out var techInfo)) continue;
foreach(var techCircleMonoPair in TechTreeCircleMonoList)
if (techCircleMonoPair.ViewType == techInfo.TechTreeCircleViewType)
{
techCircleMonoPair.CircleMono.SetContent(techInfo,OnCircleClick);
break;
}
}
return true;
}
public void RefreshStatus()
{
//Step #1 获得当前player和playerInfo
var viewPlayer = Main.MapData.PlayerMap.SelfPlayerData;
if (viewPlayer == null || !Table.Instance.PlayerDataAssets.GetPlayerInfo(viewPlayer, out var playerInfo))
{
LogSystem.LogError("UIInfoTechTreeView.InitAllTechCircle(): viewPlayer or playerInfo is null");
return;
}
// Tutor 模式 PlayerOnlyShowT2AndT22Tech 限制:仅 t2/t22 ViewType 可学,其他全部锁灰。
// 解除后下一次 RefreshStatus由 OnMatchLimitsChanged 触发)自动恢复正常状态。
bool onlyT2AndT22 = Main.MapData.MatchSettlement?.SettlementType == MatchSettlementType.Tutor
&& Main.MapData.MapConfig?.MatchLimits != null
&& Main.MapData.MapConfig.MatchLimits.Contains(MatchLimitType.PlayerOnlyShowT2AndT22Tech);
//Step #2 处理科技点 / 造山点
TechPoint.text = viewPlayer.PlayerTechPoint + "<color=blue>+" + Main.PlayerLogic.GetPlayerTechPointPerTurn(Main.MapData,viewPlayer.Id) + "</color>";
bool mountain = viewPlayer.TechTree.CheckIfHasTechAtom(TechAtom.CreateMountain);
MountainPoint.SetActive(mountain);
if (mountain)
{
var used = viewPlayer.PlayerMountainPointUsed;
var all = Main.PlayerLogic.GetPlayerMountainPoint(Main.MapData,viewPlayer.Id);
if (used >= all)
MountainCount.text = "<color=red>"+ used +"</color>/" + all;
else
MountainCount.text = used + "/" + all;
}
RefreshVikingPoint(viewPlayer);
//Step #3 处理每个circle
foreach (var tech in playerInfo.TechPool)
{
if (!Table.Instance.TechDataAssets.GetTechInfo(tech, out var techInfo)) continue;
foreach(var techCircleMonoPair in TechTreeCircleMonoList)
if (techCircleMonoPair.ViewType == techInfo.TechTreeCircleViewType)
{
bool forceLocked = onlyT2AndT22
&& techInfo.TechTreeCircleViewType != TechTreeCircleViewType.t2
&& techInfo.TechTreeCircleViewType != TechTreeCircleViewType.t22;
techCircleMonoPair.CircleMono.RefreshStatus(techInfo, forceLocked);
break;
}
}
//Step #3.5 处理T0的显隐
RefreshT0Visibility(viewPlayer, playerInfo);
//Step #3 处理每个TreeLine和TreeNode
foreach (var line in treeLineList)
{
if (line.IsNode)
line.GetComponent<Image>().color = TreeLineColorWhite;
else
line.GetComponent<Image>().color = TreeLineColorYellow;
}
foreach (var tech in playerInfo.TechPool)
{
if (viewPlayer.TechTree.CheckIfTechCanLearn(tech) || viewPlayer.TechTree.CheckIfHasTech(tech)) continue;
if (!Table.Instance.TechDataAssets.GetTechInfo(tech, out var techInfo)) continue;
foreach (var line in treeLineList)
if (line.viewType == techInfo.TechTreeCircleViewType)
line.GetComponent<Image>().color = TreeLineColorGray;
}
}
public void SetContent()
{
var player = Main.MapData.PlayerMap.SelfPlayerData;
//Step #0 处理头像
if (Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var playerInfo))
{
LeaderAvatar.sprite = playerInfo.LeaderAvatar;
ForceName.text = Logic.PlayerLogic.GetDisplayForceName(Main.MapData, player);
}
MountainPoint.SetActive(player.TechTree.CheckIfHasTechAtom(TechAtom.CreateMountain));
RefreshVikingPoint(player);
//Step #1 开局初始化 如果目前科技树上的circle已经是上一局的老版本或者这是第一次打开科技树
if(_showCivEnum != player.CivEnum || _showForceEnum != player.ForceEnum)
InitAllTechCircle();
RefreshStatus();
//Step #6 设置BGM
AudioManager.Instance.PlayMusic(playerInfo.MusicName,1f,2f,true);
}
private void Update()
{
if (!_showVikingPoint || !IsShow()) return;
RefreshVikingPointValue(Main.MapData?.PlayerMap?.SelfPlayerData);
}
private void RefreshVikingPoint(PlayerData player)
{
_showVikingPoint = ShouldShowVikingPoint(player);
if (VikingPoint != null)
VikingPoint.SetActive(_showVikingPoint);
if (!_showVikingPoint)
{
return;
}
RefreshVikingPointValue(player);
}
private void RefreshVikingPointValue(PlayerData player)
{
if (player == null || VikingCount == null) return;
EnsureVikingCountDynamicText();
var point = HakureiEinherjarCounter.GetPlayerPoints(player);
VikingCount.text = point.ToString();
}
private void EnsureVikingCountDynamicText()
{
if (VikingCount == null) return;
var multilingual = VikingCount.GetComponent<MultilingualTextMono>();
if (multilingual == null) return;
multilingual.Ban = true;
multilingual.ID = 0;
}
private static bool ShouldShowVikingPoint(PlayerData player)
{
if (player == null) return false;
if (player.CivEnum == CivEnum.Norway && player.ForceEnum == ForceEnum.Reimu) return true;
if (player.GetSkill(SkillType.HakureiEinherjarPoint, out _)) return true;
return Table.Instance?.PlayerDataAssets != null
&& Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var playerInfo)
&& playerInfo.TechPool != null
&& playerInfo.TechPool.Contains(TechType.HakureiVikingStart);
}
private void RefreshT0Visibility(PlayerData viewPlayer, PlayerInfo playerInfo)
{
TechInfo t0TechInfo = null;
foreach (var tech in viewPlayer.TechTree.TechSet)
{
if (!Table.Instance.TechDataAssets.GetTechInfo(tech, out var techInfo)) continue;
if (techInfo.TechTreeCircleViewType == TechTreeCircleViewType.t0)
{
t0TechInfo = techInfo;
break;
}
}
bool showT0 = t0TechInfo != null;
if (T0Hint != null)
T0Hint.SetActive(showT0);
foreach (var pair in TechTreeCircleMonoList)
{
if (pair.ViewType == TechTreeCircleViewType.t0)
{
pair.CircleMono.gameObject.SetActive(showT0);
if (showT0)
{
pair.CircleMono.SetContent(t0TechInfo, OnCircleClick);
pair.CircleMono.RefreshStatus(t0TechInfo);
}
break;
}
}
}
public void OnCircleClick(TechType techType)
{
CheckPanel.Open(techType);
}
/// <summary>
/// 尝试关闭 CheckPanel如果它是打开状态
/// </summary>
/// <returns>如果 CheckPanel 被关闭返回 true否则返回 false</returns>
public bool TryCloseCheckPanel()
{
if (CheckPanel != null && CheckPanel.gameObject.activeSelf)
{
CheckPanel.OnClose();
return true;
}
return false;
}
public void CloseView()
{
AudioManager.Instance.StopMusic();
Logic.Audio.AudioManager.Instance.ResumeBgmRotationIfEnabled();
}
}
}