831 lines
31 KiB
C#
831 lines
31 KiB
C#
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_Core.Managers;
|
||
using TH1_Logic.Core;
|
||
using TH1_Presentation.Sequencer.Task;
|
||
using TH1_UI.Components;
|
||
using TH1_UI.HintUI;
|
||
using TH1Renderer;
|
||
using TH1Resource;
|
||
using TMPro;
|
||
using UI.HintUI;
|
||
using Unity.VisualScripting;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TH1_UI.View.Info
|
||
{
|
||
public class UIInfoGridInfoView : Base.View
|
||
{
|
||
public Button closeButton;
|
||
public ViDelegateAssisstant.Dele OnBtnCloseClick;
|
||
|
||
[Header("Color相关")]
|
||
public Image BGUnder;
|
||
public Image BGSurface;
|
||
public Image BG2Under;
|
||
public Image BG2Surface;
|
||
public Image AvatarTitleBG;
|
||
|
||
|
||
[Header("GridInfo相关")]
|
||
public GameObject GridInfoArea;
|
||
public GameObject GridPreview;
|
||
public GameObject GridCamera;
|
||
public TextMeshProUGUI GridInfoTitle;
|
||
public TextMeshProUGUI GridInfoDesc;
|
||
public TextMeshProUGUI GridInfoTerrainTxt;
|
||
public TextMeshProUGUI GridInfoResourceTxt;
|
||
public TextMeshProUGUI GridInfoBuildingTxt;
|
||
public HintTrigger GridInfoHint;
|
||
|
||
[Header("CityInfo相关")]
|
||
public GameObject CityInfoArea;
|
||
public GameObject CityPreview;
|
||
public GameObject CityCamera;
|
||
public GameObject CityInfoDataArea;
|
||
public TextMeshProUGUI CityInfoTitle;
|
||
public TextMeshProUGUI CityInfoDesc;
|
||
public TextMeshProUGUI CityInfoCoinTxt;
|
||
public TextMeshProUGUI CityInfoTechTxt;
|
||
public TextMeshProUGUI CityInfoCultureTxt;
|
||
public TextMeshProUGUI CityInfoDiamondTxt;
|
||
public TextMeshProUGUI CityInfoPopulationTxt;
|
||
public TextMeshProUGUI CityInfoConnectTxt;
|
||
|
||
[Header("UnitInfo相关")]
|
||
public GameObject UnitInfoArea;
|
||
public Image UnitPreview;
|
||
public GameObject SkillArea;
|
||
public TextMeshProUGUI UnitInfoTitle;
|
||
public TextMeshProUGUI UnitInfoDesc;
|
||
public TextMeshProUGUI UnitInfoAttackTxt;
|
||
public TextMeshProUGUI UnitInfoDefendTxt;
|
||
public TextMeshProUGUI UnitInfoHealthTxt;
|
||
public TextMeshProUGUI UnitInfoMoveTxt;
|
||
public TextMeshProUGUI UnitInfoRangeTxt;
|
||
public TextMeshProUGUI UnitInfoMobilityTxt;
|
||
public HintTrigger UnitInfoHint;
|
||
|
||
[Header("TaskInfo相关")]
|
||
public GameObject TaskArea;
|
||
public TextMeshProUGUI TaskDesc;
|
||
|
||
|
||
[Header("CommonInfo相关")]
|
||
public GameObject AvatarArea;
|
||
|
||
public GameObject AvatarHint;
|
||
public GameObject Avatar;
|
||
public GameObject AvatarTitleArea;
|
||
public TextMeshProUGUI AvatarTitle;
|
||
public Image AvatarImg;
|
||
public Button AvatarBtn;
|
||
|
||
|
||
|
||
|
||
public GameObject ActionArea;
|
||
public TextMeshProUGUI ActionHint;
|
||
public RectTransform VerticalGroup;
|
||
public GameObject ActionCirclePrefab;
|
||
public GameObject SkillCirclePrefab;
|
||
|
||
[Header("ActionPoint相关")]
|
||
public GameObject APBox;
|
||
public Transform APContainer;
|
||
public GameObject ActionPointPrefab;
|
||
|
||
private List<UIInfoCommonBaseActionCircleMono> ActionCircleMonoList = null;
|
||
private List<UIInfoCommonBaseSkillCircleMono> SkillCircleMonoList = null;
|
||
private List<UIInfoGridInfoActionPointMono> ActionPointMonoList = null;
|
||
private int _actionCount;
|
||
protected override void OnInit()
|
||
{
|
||
base.OnInit();
|
||
ActionCircleMonoList = new List<UIInfoCommonBaseActionCircleMono>();
|
||
SkillCircleMonoList = new List<UIInfoCommonBaseSkillCircleMono>();
|
||
ActionPointMonoList = new List<UIInfoGridInfoActionPointMono>();
|
||
ActionAreaInit();
|
||
SkillAreaInit();
|
||
APBoxInit();
|
||
closeButton.onClick.RemoveAllListeners();
|
||
closeButton.onClick.AddListener(() => { OnBtnCloseClick?.Invoke(); });
|
||
//CheckPanel.InitStart(RefreshStatus);
|
||
|
||
|
||
}
|
||
|
||
//清除所有actioncircle,重新开始生成
|
||
private void ActionAreaInit()
|
||
{
|
||
if (gameObject == null) return;
|
||
for (int i = ActionArea.transform.childCount - 1; i >= 0; i--)
|
||
{
|
||
Transform child = ActionArea.transform.GetChild(i);
|
||
// 判断组件是否存在
|
||
if (child.GetComponent<UIInfoCommonBaseActionCircleMono>() != null)
|
||
{
|
||
// 正确调用 Destroy 方法,销毁子对象的 GameObject
|
||
Destroy(child.gameObject);
|
||
}
|
||
}
|
||
|
||
ActionCircleMonoList.Clear();
|
||
ActionCircleMonoList = new List<UIInfoCommonBaseActionCircleMono>();
|
||
}
|
||
|
||
private void SkillAreaInit()
|
||
{
|
||
if (gameObject == null) return;
|
||
for (int i = SkillArea.transform.childCount - 1; i >= 0; i--)
|
||
{
|
||
Transform child = SkillArea.transform.GetChild(i);
|
||
// 判断组件是否存在
|
||
if (child.GetComponent<UIInfoCommonBaseSkillCircleMono>() != null)
|
||
{
|
||
// 正确调用 Destroy 方法,销毁子对象的 GameObject
|
||
Destroy(child.gameObject);
|
||
}
|
||
}
|
||
|
||
SkillCircleMonoList.Clear();
|
||
SkillCircleMonoList = new List<UIInfoCommonBaseSkillCircleMono>();
|
||
}
|
||
|
||
public void SetContent(ShowUIInfoGridInfo evt)
|
||
{
|
||
SetContentAvatar(evt);
|
||
SetContentGrid(evt);
|
||
SetContentUnit(evt);
|
||
SetContentCity(evt);
|
||
SetContentSkill(evt);
|
||
SetContentAction(evt);
|
||
SetContentAPBox(evt);
|
||
SetContentTask(evt);
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(VerticalGroup);
|
||
}
|
||
|
||
private void SetContentAvatar(ShowUIInfoGridInfo evt)
|
||
{
|
||
AvatarArea.SetActive(true);
|
||
|
||
PlayerData player = null;
|
||
switch (evt.type)
|
||
{
|
||
case UIGridInfoType.grid: // City is on a grid, so its ID is a GID
|
||
Main.MapData.GetPlayerDataByTerritoryGridId(evt.id, out player);
|
||
break;
|
||
case UIGridInfoType.unit:
|
||
Main.MapData.GetPlayerDataByUnitId(evt.id, out player);
|
||
break;
|
||
}
|
||
|
||
if (player == null || !Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var info))
|
||
{
|
||
AvatarTitleArea.SetActive(false);
|
||
AvatarHint.SetActive(false);
|
||
Avatar.SetActive(false);
|
||
|
||
//设置中立领土颜色
|
||
SetColor(Table.Instance.PlayerDataAssets.CommonColor);
|
||
return;
|
||
}
|
||
|
||
AvatarTitleArea.SetActive(true);
|
||
AvatarHint.SetActive(true);
|
||
Avatar.SetActive(true);
|
||
|
||
Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var playerInfo);
|
||
SetColor(playerInfo?.Color ?? Color.black);
|
||
|
||
if(!Main.MapData.PlayerMap.SelfPlayerData.MeetPlayers.Contains(player.Id))
|
||
{
|
||
AvatarBtn.onClick.RemoveAllListeners();
|
||
AvatarImg.sprite = Table.Instance.PlayerDataAssets.CommonPlayerAvatar;
|
||
AvatarTitle.text = "???";
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(AvatarTitleArea.GetComponent<RectTransform>());
|
||
return;
|
||
}
|
||
|
||
|
||
AvatarImg.sprite = info.LeaderAvatar;
|
||
MultilingualManager.Instance.SetUIText(AvatarTitle,info.ForceName);
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(AvatarTitleArea.GetComponent<RectTransform>());
|
||
|
||
AvatarBtn.onClick.RemoveAllListeners();
|
||
AvatarBtn.onClick.AddListener(() =>
|
||
{
|
||
EventManager.Publish(new ShowUIInfoDiplomacy() { Pid = player.Id });
|
||
//因为gridinfo和diplomacyinfo 同属infoUI,打开diploInfo会自动关闭gridinfo,这里如果再主动关闭自身,会重复关闭导致错误
|
||
//OnBtnCloseClick?.Invoke();
|
||
});
|
||
}
|
||
|
||
private void SetColor(Color color)
|
||
{
|
||
var colorUnder = color;
|
||
colorUnder.a = 0.4f;
|
||
BGUnder.color = colorUnder;
|
||
BGSurface.color = color;
|
||
BG2Under.color = colorUnder;
|
||
BG2Surface.color = color;
|
||
AvatarTitleBG.color = color;
|
||
|
||
}
|
||
|
||
private void SetContentGrid(ShowUIInfoGridInfo evt)
|
||
{
|
||
if (evt.type != UIGridInfoType.grid || !Main.MapData.GridMap.GetGridDataByGid(evt.id, out var grid) || Main.MapData.GetCityDataByGid(evt.id, out var _))
|
||
{
|
||
GridInfoArea.SetActive(false);
|
||
return;
|
||
}
|
||
GridInfoArea.SetActive(true);
|
||
|
||
|
||
//Step #1 GridPreview
|
||
|
||
GameObject clone =
|
||
Instantiate(MapRenderer.Instance.ROGridMap[evt.id].GetROGrid() as GameObject);
|
||
for (int i = GridPreview.transform.childCount - 1; i >= 0; i--)
|
||
Destroy(GridPreview.transform.GetChild(i).gameObject);
|
||
clone.transform.SetParent(GridPreview.transform);
|
||
clone.transform.localPosition = new Vector3(0,15,0);
|
||
clone.transform.Find("SelectHighlight").gameObject.SetActive(false);
|
||
SetLayerRecursively(clone, LayerMask.NameToLayer("Preview"));
|
||
GridCamera.SetActive(true);
|
||
Timer.Instance.TimerRegister(GridCamera, () => { GridCamera.SetActive(false); }, 0.001f,"HideCamera");
|
||
|
||
|
||
//Step #2 Title & Desc
|
||
//title 逻辑 -> building > resource > forest > mountain > plain
|
||
string title_DECODE = "";
|
||
string desc_DECODE = "";
|
||
|
||
|
||
Empire empire = new Empire(grid.CivEnum,grid.Player(Main.MapData)?.ForceEnum??ForceEnum.Common);
|
||
var spType = grid.GetTopGridSpType();
|
||
//如果是奇观
|
||
if (grid.Resource == ResourceType.Wonder)
|
||
{
|
||
|
||
|
||
if (Table.Instance.GridAndResourceDataAssets.GetWonderInfo(grid.Wonder, out var info))
|
||
{
|
||
title_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(info.Name);
|
||
desc_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(info.Desc);
|
||
}
|
||
}
|
||
//如果显示建筑或者资源
|
||
else if (grid.Resource != ResourceType.None && Main.MapData.PlayerMap.SelfPlayerData.CanShowResource(grid.Resource))
|
||
{
|
||
title_DECODE = Table.Instance.GridAndResourceDataAssets.GetResourceNameWithLevel_DECODE(grid,empire,spType);
|
||
//var spr = Table.Instance.GridAndResourceDataAssets.GetResourceSprite(grid.Resource, grid.Player(Main.MapData), grid);
|
||
Table.Instance.GridAndResourceDataAssets.GetResourceInfo(grid.Resource, out var resourceInfo);
|
||
desc_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(resourceInfo.GetResourceDesc(empire,spType));
|
||
}
|
||
//如果显示树木
|
||
else if(grid.Vegetation == Vegetation.Trees)
|
||
{
|
||
Table.Instance.GridAndResourceDataAssets.GetVegetationInfo(out var vegetationInfo);
|
||
title_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(vegetationInfo.GetResourceName(empire,spType));
|
||
desc_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(vegetationInfo.GetResourceDesc(empire,spType));
|
||
}
|
||
//如果显示山脉
|
||
else if(grid.Feature == TerrainFeature.Mountain)
|
||
{
|
||
Table.Instance.GridAndResourceDataAssets.GetMountainInfo(out var mountainInfo);
|
||
title_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(mountainInfo.ResourceName);
|
||
desc_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(mountainInfo.ResourceDesc);
|
||
}
|
||
//如果显示地形
|
||
else
|
||
{
|
||
Table.Instance.GridAndResourceDataAssets.GetTerrainInfo(grid.Terrain, out var terrainInfo);
|
||
title_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(terrainInfo.ResourceName);
|
||
desc_DECODE = MultilingualManager.Instance.GetMultilingualTextSafe(terrainInfo.ResourceDesc);
|
||
}
|
||
GridInfoTitle.text = title_DECODE;
|
||
GridInfoDesc.text = desc_DECODE;
|
||
|
||
//Step #3 设置详细info
|
||
//resource / building
|
||
if (grid.Resource != ResourceType.None && Table.Instance.GridAndResourceDataAssets.GetResourceInfo(grid.Resource, out var resourceInfo2))
|
||
{
|
||
if (resourceInfo2.ResourceSubType == ResourceSubType.Building)
|
||
{
|
||
GridInfoBuildingTxt.text = Table.Instance.GridAndResourceDataAssets.GetResourceNameWithLevel_DECODE(grid,empire,spType);
|
||
//处理盖在建筑下面的资源
|
||
if (grid.ResourceUnderBuilding != ResourceType.None &&
|
||
Table.Instance.GridAndResourceDataAssets.GetResourceInfo(grid.ResourceUnderBuilding,
|
||
out var resourceInfo3) && resourceInfo3.ResourceSubType == ResourceSubType.Resource)
|
||
MultilingualManager.Instance.SetUIText(GridInfoResourceTxt,
|
||
Table.Instance.GridAndResourceDataAssets.GetResourceName(grid.ResourceUnderBuilding,empire,spType));
|
||
else GridInfoResourceTxt.text = "-";
|
||
}
|
||
else
|
||
{
|
||
GridInfoBuildingTxt.text = "-";
|
||
if(Main.MapData.PlayerMap.SelfPlayerData.CanShowResource(grid.Resource))
|
||
MultilingualManager.Instance.SetUIText(GridInfoResourceTxt, Table.Instance.GridAndResourceDataAssets.GetResourceName(grid.Resource,empire,spType));
|
||
else GridInfoResourceTxt.text = "-";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
GridInfoBuildingTxt.text = "-";
|
||
GridInfoResourceTxt.text = "-";
|
||
}
|
||
//terrain
|
||
if (grid.Feature == TerrainFeature.Mountain)
|
||
{
|
||
Table.Instance.GridAndResourceDataAssets.GetMountainInfo(out var mountainInfo);
|
||
MultilingualManager.Instance.SetUIText(GridInfoTerrainTxt, mountainInfo.ResourceName);
|
||
}
|
||
else if (grid.Vegetation == Vegetation.Trees)
|
||
{
|
||
Table.Instance.GridAndResourceDataAssets.GetVegetationInfo(out var vegetationInfo);
|
||
MultilingualManager.Instance.SetUIText(GridInfoTerrainTxt, vegetationInfo.ResourceName);
|
||
}
|
||
else
|
||
{
|
||
Table.Instance.GridAndResourceDataAssets.GetTerrainInfo(grid.Terrain,out var terrainInfo);
|
||
MultilingualManager.Instance.SetUIText(GridInfoTerrainTxt, terrainInfo.ResourceName);
|
||
}
|
||
|
||
//处理GeoHintInfo
|
||
//TODO 不能在这里修改mapData,这是错误的, 必须要调用action 来修改mapData
|
||
grid.UpdateGeoInfo(Main.MapData);
|
||
if (grid.GeoIdList?.Count > 0)
|
||
{
|
||
GridInfoHint.gameObject.SetActive(true);
|
||
GridInfoHint.DataProvider.HintDataType = HintDataType.GeoData;
|
||
|
||
|
||
|
||
GridInfoHint.DataProvider.GeoIdList = grid.GetRealTimeGeoIdList();
|
||
}
|
||
else
|
||
{
|
||
GridInfoHint.gameObject.SetActive(false);
|
||
}
|
||
|
||
}
|
||
|
||
private void SetContentUnit(ShowUIInfoGridInfo evt)
|
||
{
|
||
if (evt.type != UIGridInfoType.unit || !Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unitData))
|
||
{
|
||
UnitInfoArea.SetActive(false);
|
||
return;
|
||
}
|
||
UnitInfoArea.SetActive(true);
|
||
// 获取关联数据
|
||
Main.MapData.GetPlayerDataByUnitId(unitData.Id, out var playerData);
|
||
Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitData.UnitFullType, out var unitTypeInfo);
|
||
|
||
// Step #1: Unit Preview
|
||
if (Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, unitData, out var spr))
|
||
UnitPreview.sprite = spr;
|
||
|
||
|
||
// Step #2: Title & Description
|
||
// 逻辑参考 BottomInfoUI.cs -> UpdateInfoUnit
|
||
string title = MultilingualManager.Instance.GetMultilingualTextSafe(unitTypeInfo.Name);
|
||
|
||
//处理Officer的情况
|
||
if (unitData.IsOfficer()) title += "("+ MultilingualManager.Instance.GetMultilingualText(Table.Instance.TextDataAssets.UnitOfficerName)+")"; // 示例
|
||
else if (unitData.IsPrepareOfficer()) title += $"({unitData.GetKillCount()}/3)";
|
||
|
||
UnitInfoTitle.text = title;
|
||
MultilingualManager.Instance.SetUIText(UnitInfoDesc, unitTypeInfo.Desc);
|
||
// Step #3: Core Stats
|
||
UnitInfoHealthTxt.text = $"{unitData.Health}/{unitData.GetMaxHealth()}";
|
||
UnitInfoAttackTxt.text = unitData.GetAttackShowString(Main.MapData);
|
||
UnitInfoDefendTxt.text = unitData.GetDefenseShowString(Main.MapData);
|
||
UnitInfoMoveTxt.text = unitData.GetMoveRangeShowString(Main.MapData);
|
||
UnitInfoRangeTxt.text = unitData.GetAttackRangeShowString(Main.MapData);
|
||
UnitInfoMobilityTxt.text = Table.Instance.MobilityDataAssets.GetLandTypeText_DECODE(unitTypeInfo.LandType);
|
||
|
||
//Step #4 处理Giant Hint
|
||
bool isgiant = unitData.UnitFullType.UnitType is UnitType.Giant or UnitType.GiantJuggernaut;
|
||
UnitInfoHint.gameObject.SetActive(isgiant);
|
||
if (isgiant)
|
||
{
|
||
UnitInfoHint.DataProvider.HintDataType = HintDataType.TextDataGiantUpgrate;
|
||
UnitInfoHint.DataProvider.UnitFullType = unitData.UnitFullType;
|
||
}
|
||
|
||
}
|
||
|
||
private void SetContentCity(ShowUIInfoGridInfo evt)
|
||
{
|
||
if (evt.type != UIGridInfoType.grid || !Main.MapData.GetCityDataByGid(evt.id,out var city)
|
||
|| !Main.MapData.GetPlayerDataByCityId(city.Id, out var player))
|
||
{
|
||
CityInfoArea.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
|
||
//TODO 这里临时去现实city的border
|
||
foreach (var gid in city.Territory.TerritoryArea)
|
||
if(Main.MapData.GridMap.GetGridDataByGid(gid,out var gridData))
|
||
gridData.CityBorderRenderMark = true;
|
||
|
||
|
||
|
||
CityInfoArea.SetActive(true);
|
||
|
||
// Step 1: Preview (Placeholder)
|
||
GameObject clone =
|
||
Instantiate(MapRenderer.Instance.ROGridMap[evt.id].GetROGrid() as GameObject);
|
||
for (int i = CityPreview.transform.childCount - 1; i >= 0; i--)
|
||
Destroy(CityPreview.transform.GetChild(i).gameObject);
|
||
clone.transform.SetParent(CityPreview.transform);
|
||
clone.transform.localPosition = new Vector3(0,15,0);
|
||
clone.transform.Find("SelectHighlight").gameObject.SetActive(false);
|
||
SetLayerRecursively(clone, LayerMask.NameToLayer("Preview"));
|
||
CityCamera.SetActive(true);
|
||
Timer.Instance.TimerRegister(CityCamera, () => { CityCamera.SetActive(false); }, 0.001f,"HideCamera");
|
||
|
||
// Step 2: Title & Description
|
||
Table.Instance.CivDataAssets.GetCityInfo(city.Name, out var cityInfo);
|
||
CityInfoTitle.text = MultilingualManager.Instance.GetMultilingualTextSafe(cityInfo.CityName) + " Lv." + city.Level;
|
||
MultilingualManager.Instance.SetUIText(CityInfoDesc, cityInfo.CityDescription);
|
||
|
||
// Step 3: Detailed Info (differs for self vs. others)
|
||
if (player.Id == Main.MapData.PlayerMap.SelfPlayerData.Id)
|
||
{
|
||
CityInfoDataArea.SetActive(true);
|
||
var tb = Table.Instance.TextDataAssets;
|
||
CityInfoCoinTxt.text = "+" + Main.CityLogic.GetCityCoinPerTurn(Main.MapData, city)+ MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_PerTurn);
|
||
CityInfoTechTxt.text = "+" + Main.CityLogic.GetCityTechPointPerTurn(Main.MapData, city) + MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_PerTurn);
|
||
//var culturePerTurn = Main.CityLogic.GetCityCulturePointPerTurn(Main.MapData, city);
|
||
//CityInfoCultureTxt.text = "+" + culturePerTurn + MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_PerTurn);
|
||
//CityInfoCultureTxt.gameObject.SetActive(culturePerTurn > 0);
|
||
CityInfoPopulationTxt.text = MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_Population) + Main.MapData.GetUnitCount(city.Id) + "/" + city.Level;
|
||
CityInfoDiamondTxt.text = city.ParkCount + MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_Diamond);
|
||
CityInfoConnectTxt.text = city.IsCapital ? MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_Capital) : (city.IsConnectedCapital ? MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_Connected) :
|
||
MultilingualManager.Instance.GetMultilingualTextSafe(tb.GridInfoText_Unconnected));
|
||
}
|
||
else
|
||
CityInfoDataArea.SetActive(false);
|
||
|
||
|
||
|
||
}
|
||
|
||
private void SetContentSkill(ShowUIInfoGridInfo evt)
|
||
{
|
||
if (evt.type != UIGridInfoType.unit)
|
||
{
|
||
SkillArea.SetActive(false);
|
||
return;
|
||
}
|
||
if (!Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unit)) return;
|
||
|
||
var skillList = new List<SkillBase>();
|
||
foreach (var skill in unit.Skills)
|
||
{
|
||
if(!Table.Instance.SkillDataAssets.GetSkillInfo(skill.GetSkillType(), out var info)
|
||
|| info.NotShow)continue;
|
||
skillList.Add(skill);
|
||
}
|
||
|
||
if (skillList.Count == 0)
|
||
{
|
||
SkillArea.SetActive(false);
|
||
return;
|
||
}
|
||
SkillArea.SetActive(true);
|
||
|
||
|
||
//Step #2 确定格位够不够
|
||
while (SkillCircleMonoList.Count < skillList.Count)
|
||
{
|
||
GameObject actionCircle = Instantiate(SkillCirclePrefab, SkillArea.transform, true);
|
||
actionCircle.GetComponent<RectTransform>().localScale = Vector3.one;
|
||
actionCircle.GetComponent<RectTransform>().localPosition = Vector3.zero;
|
||
SkillCircleMonoList.Add(actionCircle.GetComponent<UIInfoCommonBaseSkillCircleMono>());
|
||
}
|
||
//Step #3 skill分类sort序列
|
||
var skillSort = new List<int>();
|
||
var skillViewType = new List<SkillViewType>();
|
||
foreach (var t in skillList)
|
||
{
|
||
Table.Instance.SkillDataAssets.GetSkillInfo(t.GetSkillType(), out var info);
|
||
var viewType = info?.SkillViewType ?? SkillViewType.Normal;
|
||
if (t.HasTimeLimit && viewType != SkillViewType.Positive && viewType != SkillViewType.Negative)
|
||
viewType = SkillViewType.Positive;
|
||
skillViewType.Add(viewType);
|
||
}
|
||
for(int i = 0;i < skillList.Count; i++)if(skillViewType.Count > i && skillViewType[i] == SkillViewType.Normal)skillSort.Add(i);
|
||
for(int i = 0;i < skillList.Count; i++)if(skillViewType.Count > i && skillViewType[i] == SkillViewType.Special)skillSort.Add(i);
|
||
for(int i = 0;i < skillList.Count; i++)if(skillViewType.Count > i && skillViewType[i] == SkillViewType.Unique)skillSort.Add(i);
|
||
for(int i = 0;i < skillList.Count; i++)if(skillViewType.Count > i && skillViewType[i] == SkillViewType.Positive)skillSort.Add(i);
|
||
for(int i = 0;i < skillList.Count; i++)if(skillViewType.Count > i && skillViewType[i] == SkillViewType.Negative)skillSort.Add(i);
|
||
|
||
|
||
//Step #3 设置每一个action
|
||
//bool unitIsBanned = unit.IsFrozen();
|
||
for (int i = 0; i < SkillCircleMonoList.Count; i++)
|
||
if (i < skillSort.Count && skillSort[i] < skillList.Count)
|
||
{
|
||
var skill = skillList[skillSort[i]];
|
||
bool isBanned = skill.IsFrozen(unit);
|
||
SkillCircleMonoList[i].gameObject.SetActive(true);
|
||
SkillCircleMonoList[i].SetContent(skill,unit.UnitFullType,isBanned);
|
||
}
|
||
else
|
||
SkillCircleMonoList[i].gameObject.SetActive(false);
|
||
|
||
|
||
}
|
||
|
||
private void SetContentAction(ShowUIInfoGridInfo evt)
|
||
{
|
||
//观战模式:非自己回合时不显示Action区域
|
||
if (Main.MapData.CurPlayer != Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
ActionArea.SetActive(false);
|
||
_actionCount = 0;
|
||
return;
|
||
}
|
||
|
||
//Step #1 获取actionList
|
||
//ResourceCache.Instance.SpriteCache.ActionBGAvailable
|
||
var actionList = new List<ActionLogicBase>();
|
||
var cantTypeList = new List<ShowType>();
|
||
bool showAction = false;
|
||
var subType = evt.type;
|
||
CommonActionParams param = null;
|
||
if (subType == UIGridInfoType.unit && Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id,out var unit))
|
||
{
|
||
param = new CommonActionParams(mapData:Main.MapData,playerData:Main.MapData.PlayerMap.SelfPlayerData,unitData:unit,mainObjectType:MainObjectType.Unit);
|
||
showAction = ActionLogicFactory.MainObjectCanShowAction(param, out actionList,out cantTypeList);
|
||
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_UnitInfoHint);
|
||
|
||
}
|
||
else if (subType == UIGridInfoType.grid && Main.MapData.GetCityDataByGid(evt.id,out var city))
|
||
{
|
||
param = new CommonActionParams(mapData:Main.MapData,playerData:Main.MapData.PlayerMap.SelfPlayerData,cityData:city,mainObjectType:MainObjectType.City);
|
||
showAction = ActionLogicFactory.MainObjectCanShowAction(param,out actionList,out cantTypeList);
|
||
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_CityInfoHint);
|
||
}
|
||
else if (subType == UIGridInfoType.grid && Main.MapData.GridMap.GetGridDataByGid(evt.id,out var grid))
|
||
{
|
||
param = new CommonActionParams(mapData:Main.MapData,Main.MapData.PlayerMap.SelfPlayerData,gridData:grid,mainObjectType:MainObjectType.Grid);
|
||
showAction = ActionLogicFactory.MainObjectCanShowAction(param,out actionList,out cantTypeList);
|
||
if(grid.Resource is ResourceType.Military or ResourceType.RemiliaMilitary)
|
||
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_CityInfoHint);
|
||
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_GridInfoHint);
|
||
}
|
||
|
||
if (!showAction)
|
||
{
|
||
// 我方Unit即使没有Action也保留ActionArea(用于显示APBox),但隐藏标题
|
||
bool isSelfUnit = subType == UIGridInfoType.unit
|
||
&& Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var selfCheckUnit)
|
||
&& Main.MapData.GetPlayerDataByUnitId(evt.id, out var selfCheckPlayer)
|
||
&& selfCheckPlayer.Id == Main.MapData.PlayerMap.SelfPlayerData.Id;
|
||
if (isSelfUnit)
|
||
{
|
||
ActionArea.SetActive(true);
|
||
ActionHint.gameObject.SetActive(false);
|
||
// 隐藏所有ActionCircle
|
||
for (int i = 0; i < ActionCircleMonoList.Count; i++)
|
||
ActionCircleMonoList[i].gameObject.SetActive(false);
|
||
_actionCount = 0;
|
||
return;
|
||
}
|
||
|
||
ActionArea.SetActive(false);
|
||
//_actionCount必须设置为0,因为其他地方会用到
|
||
_actionCount = 0;
|
||
return;
|
||
}
|
||
ActionArea.SetActive(true);
|
||
ActionHint.gameObject.SetActive(true);
|
||
_actionCount = actionList.Count;
|
||
//Step #2 确定格位够不够
|
||
while (ActionCircleMonoList.Count < actionList.Count)
|
||
{
|
||
GameObject actionCircle = Instantiate(ActionCirclePrefab, ActionArea.transform, true);
|
||
actionCircle.GetComponent<RectTransform>().localScale = Vector3.one;
|
||
actionCircle.GetComponent<RectTransform>().localPosition = Vector3.zero;
|
||
ActionCircleMonoList.Add(actionCircle.GetComponent<UIInfoCommonBaseActionCircleMono>());
|
||
}
|
||
|
||
//Step #3 设置每一个action
|
||
for (int i = 0; i < ActionCircleMonoList.Count; i++)
|
||
{
|
||
ActionCircleMonoList[i].gameObject.SetActive(i < actionList.Count);
|
||
if (i >= actionList.Count) continue;
|
||
ActionCircleMonoList[i].SetContent(actionList[i].ActionId,cantTypeList[i],param,OnActionCircleClicked);
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
public void ExecuteAction(ExecuteUIInfoGridInfo evt)
|
||
{
|
||
if(evt.idx >= ActionCircleMonoList.Count || evt.idx >= _actionCount) return;
|
||
ActionCircleMonoList[(int)evt.idx].ClickButton.onClick.Invoke();
|
||
}
|
||
private void OnActionCircleClicked(CommonActionId actionId, CommonActionParams param)
|
||
{
|
||
var action = ActionLogicFactory.GetActionLogic(actionId);
|
||
if (action.CheckCan(param) && action.CompleteExecute(param))
|
||
{
|
||
// Action执行成功后立即刷新APBox,确保关闭/重开面板时显示最新状态
|
||
if (param.UnitData != null)
|
||
RefreshActionPoints(param.UnitData);
|
||
|
||
OnBtnCloseClick?.Invoke();
|
||
|
||
//这里特殊处理 点击了action但是不关闭gridInfo而是让单位继续行动的情况。后续需要将这个属性归化
|
||
if(action.ActionId.UnitActionType == UnitActionType.AYAMOVEAGAIN)
|
||
PresentationManager.EnqueueTask(new InputSequencerTask(MapRenderer.Instance.SelectUnitData.Grid(Main.MapData)));
|
||
}
|
||
}
|
||
|
||
//清除所有ActionPoint,重新开始
|
||
private void APBoxInit()
|
||
{
|
||
if (APContainer == null) return;
|
||
for (int i = APContainer.childCount - 1; i >= 0; i--)
|
||
{
|
||
Transform child = APContainer.GetChild(i);
|
||
if (child.GetComponent<UIInfoGridInfoActionPointMono>() != null)
|
||
Destroy(child.gameObject);
|
||
}
|
||
ActionPointMonoList.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据当前GridInfo展示的类型,决定APBox是否显示,以及填充ActionPoint列表。
|
||
/// 仅在展示Unit的ActionArea时才显示APBox。
|
||
/// </summary>
|
||
private void SetContentAPBox(ShowUIInfoGridInfo evt)
|
||
{
|
||
// 只有当展示的是Unit,并且ActionArea可见时,才显示APBox
|
||
if (evt.type != UIGridInfoType.unit
|
||
|| !Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unitData)
|
||
|| !ActionArea.activeSelf)
|
||
{
|
||
if (APBox != null) APBox.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
if (APBox != null) APBox.SetActive(true);
|
||
RefreshActionPoints(unitData);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新APContainer下ActionPoint的数量和显示内容。
|
||
/// 根据unitData里的行动点信息,动态生成/复用/隐藏ActionPoint对象。
|
||
/// </summary>
|
||
public void RefreshActionPoints(RuntimeData.UnitData unitData)
|
||
{
|
||
if (APContainer == null || ActionPointPrefab == null || unitData == null) return;
|
||
|
||
// 将ActionPoint字典展开为一个平铺列表,每个点一个条目
|
||
var flatList = new List<RuntimeData.ActionPointType>();
|
||
if (unitData.ActionPoint != null)
|
||
{
|
||
foreach (var kv in unitData.ActionPoint)
|
||
{
|
||
for (int j = 0; j < kv.Value; j++)
|
||
flatList.Add(kv.Key);
|
||
}
|
||
}
|
||
|
||
// 如果总量为0,仍然显示一个Empty
|
||
int needCount = flatList.Count > 0 ? flatList.Count : 1;
|
||
|
||
// 确保池中有足够的ActionPoint实例
|
||
while (ActionPointMonoList.Count < needCount)
|
||
{
|
||
GameObject go = Instantiate(ActionPointPrefab, APContainer, false);
|
||
go.GetComponent<RectTransform>().localScale = Vector3.one;
|
||
var mono = go.GetComponent<UIInfoGridInfoActionPointMono>();
|
||
if (mono == null) mono = go.AddComponent<UIInfoGridInfoActionPointMono>();
|
||
ActionPointMonoList.Add(mono);
|
||
}
|
||
|
||
// 设置每个ActionPoint的显示/隐藏和内容
|
||
for (int i = 0; i < ActionPointMonoList.Count; i++)
|
||
{
|
||
if (i < needCount)
|
||
{
|
||
ActionPointMonoList[i].gameObject.SetActive(true);
|
||
if (flatList.Count == 0)
|
||
ActionPointMonoList[i].SetEmpty();
|
||
else
|
||
ActionPointMonoList[i].SetContent(flatList[i]);
|
||
}
|
||
else
|
||
{
|
||
ActionPointMonoList[i].gameObject.SetActive(false);
|
||
ActionPointMonoList[i].ResetContent();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void SetLayerRecursively(GameObject obj, int newLayer)
|
||
{
|
||
obj.layer = newLayer;
|
||
|
||
foreach (Transform child in obj.transform)
|
||
{
|
||
SetLayerRecursively(child.gameObject, newLayer);
|
||
}
|
||
}
|
||
|
||
private void SetContentTask(ShowUIInfoGridInfo evt)
|
||
{
|
||
// Step #1 判断是否有task需要显示
|
||
if (evt.type != UIGridInfoType.unit ||
|
||
!Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unit) ||
|
||
!Main.MapData.GetPlayerDataByUnitId(evt.id, out var player) )
|
||
{
|
||
TaskArea.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
bool shouldShowTask = (unit.UnitFullType.UnitType is UnitType.Giant or UnitType.GiantJuggernaut)&&
|
||
unit.UnitFullType.UnitLevel < 4 &&
|
||
player.Id == Main.MapData.PlayerMap.SelfPlayerId;
|
||
if (!shouldShowTask)
|
||
{
|
||
TaskArea.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
//Step #2 设置具体内容
|
||
TaskArea.SetActive(true);
|
||
if (!Table.Instance.HeroDataAssets.GetHeroInfo(unit.GiantType, out var heroInfo) ||
|
||
heroInfo.TaskList.Count <= unit.UnitLevel - 1 ||
|
||
!Main.MapData.PlayerMap.SelfPlayerData.PlayerHeroData.GetHeroTask(unit.GiantType, out var task))
|
||
{
|
||
TaskArea.SetActive(false);
|
||
return;
|
||
}
|
||
if (task.IsForceFinished)
|
||
{
|
||
MultilingualManager.Instance.SetUIText(TaskDesc, Table.Instance.TextDataAssets.HeroTaskFinishedDesc);
|
||
}
|
||
else
|
||
{
|
||
var param1 = task.LevelShowString();
|
||
var param2 = task.TargetLevelShowString();
|
||
var param3 = "";
|
||
if (task.SkillType != SkillType.NONE && Table.Instance.SkillDataAssets.GetSkillInfo(task.SkillType, out var skillInfo))
|
||
{
|
||
param3 = MultilingualManager.Instance.GetMultilingualTextSafe(skillInfo.SkillName);
|
||
}
|
||
var taskDesc = heroInfo.TaskList[(int)(unit.UnitLevel - 1)].Desc;
|
||
MultilingualManager.Instance.SetUIText(TaskDesc, taskDesc, new List<string> { param1, param2, param3 });
|
||
}
|
||
}
|
||
|
||
public void CloseView()
|
||
{
|
||
// 不停止音乐,只恢复轮播(如果正在播放的不是轮播音乐,会继续播放)
|
||
Logic.Audio.AudioManager.Instance.ResumeBgmRotationIfEnabled();
|
||
}
|
||
|
||
protected override void OnShowAnimFinished()
|
||
{
|
||
base.OnShowAnimFinished();
|
||
|
||
// 延迟一帧执行布局刷新,确保 RectTransform 尺寸已正确计算
|
||
StartCoroutine(RefreshLayoutNextFrame());
|
||
}
|
||
|
||
private System.Collections.IEnumerator RefreshLayoutNextFrame()
|
||
{
|
||
yield return null; // 等待一帧
|
||
if (VerticalGroup != null)
|
||
{
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(VerticalGroup);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
}
|