411 lines
16 KiB
C#
411 lines
16 KiB
C#
using Logic;
|
||
using Logic.CrashSight;
|
||
using Logic.Multilingual;
|
||
using RuntimeData;
|
||
using TH1_Logic.Core;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
|
||
namespace TH1_Renderer
|
||
{
|
||
public class CityInfoRenderer
|
||
{
|
||
private MapData _mapData;
|
||
//private GameObject _ROCityInfo;
|
||
//private GameObject _RODebugText;
|
||
//private TextMeshProUGUI _debugText;
|
||
private uint _cityId;
|
||
|
||
//-------- Update缓存数据 --------//
|
||
private CityData _cityData;
|
||
|
||
private CityInfoMono _cityInfoMono;
|
||
|
||
public CityInfoRenderer(GameObject prefab,Transform father, uint cid, MapData mapData, Main main)
|
||
{
|
||
_mapData = mapData;
|
||
_cityId = cid;
|
||
_mapData.CityMap.GetCityById(_cityId,out _cityData);
|
||
Vector3 tpos = Table.Instance.GridToWorld(_cityData.Grid(mapData) ?? null,"isCityInfo");
|
||
|
||
var obj = GameObject.Instantiate(prefab,tpos, Quaternion.identity, father);
|
||
_cityInfoMono = obj.GetComponent<CityInfoMono>();
|
||
//_RODebugText = _ROCityInfo.transform.Find("CityInfoCanvas/DebugText").gameObject;
|
||
//_debugText = _RODebugText.GetComponent<TextMeshProUGUI>();
|
||
}
|
||
|
||
public void Update()
|
||
{
|
||
_mapData.CityMap.GetCityById(_cityId,out _cityData);
|
||
//RenderUpdateDebug();
|
||
}
|
||
|
||
// 销毁渲染器的 GameObject。用于 MapRenderer.RepairAllRenderers 清理孤儿。
|
||
public void Dispose()
|
||
{
|
||
if (_cityInfoMono != null)
|
||
{
|
||
GameObject.Destroy(_cityInfoMono.gameObject);
|
||
_cityInfoMono = null;
|
||
}
|
||
_cityData = null;
|
||
}
|
||
|
||
//瞬间生效的动画函数,将cityinfo的所有视觉瞬间与数据完全同步
|
||
public void InstantUpdateCityInfo()
|
||
{
|
||
RenderUpdateCityInfo();
|
||
}
|
||
|
||
//瞬间生效的动画,将所有图标相关的视觉瞬间与数据完全同步
|
||
public void InstantUpdateCityLabels()
|
||
{
|
||
var player = _cityData.Player(Main.MapData);
|
||
var isSelfCity = player == _mapData.PlayerMap.SelfPlayerData;
|
||
var isCradleCity = Main.CityLogic.CheckCradleCapital(_mapData, player, _cityData);
|
||
//更新联通图标的情况
|
||
_cityInfoMono?.SetConnect( isSelfCity && !isCradleCity && _cityData.IsConnectedCapital);
|
||
//更新首都图标的情况
|
||
_cityInfoMono?.SetCapital(isCradleCity && isSelfCity);
|
||
//更新大使馆图标的情况
|
||
GetEmbassyIconStatus(out bool showEmbassy,out bool showWarEmbassy);
|
||
_cityInfoMono?.SetEmbassy(showEmbassy);
|
||
_cityInfoMono?.SetWarEmbassy(showWarEmbassy);
|
||
//更新被Cloak偷金币的图标
|
||
_cityInfoMono?.SetCityStolen(_cityData.GetSkill(SkillType.CITYSTOLEN, out _));
|
||
}
|
||
|
||
public void InstantUpdateCityCoinTech()
|
||
{
|
||
RenderUpdateCityCoinTech();
|
||
}
|
||
|
||
public void InstantUpdateCityCoinTechCulture()
|
||
{
|
||
RenderUpdateCityCoinTechCulture();
|
||
}
|
||
|
||
|
||
private void RenderUpdateCityInfo()
|
||
{
|
||
if (_mapData == null)
|
||
{
|
||
LogSystem.LogError("RenderUpdateCityInfo _mapData == null");
|
||
return;
|
||
}
|
||
|
||
if (_cityData == null)
|
||
{
|
||
LogSystem.LogError("RenderUpdateCityInfo _cityData == null");
|
||
return;
|
||
}
|
||
|
||
if (_mapData.PlayerMap?.SelfPlayerData == null || _mapData.CityToPlayerDict == null ||
|
||
_mapData.CityToGridDict == null || _mapData.GridMap == null)
|
||
{
|
||
LogSystem.LogError("RenderUpdateCityInfo _mapData missing player/city/grid data");
|
||
return;
|
||
}
|
||
|
||
var mainMapData = Main.MapData;
|
||
if (mainMapData?.PlayerMap?.SelfPlayerData == null || mainMapData.CityToPlayerDict == null ||
|
||
mainMapData.CityToGridDict == null || mainMapData.GridMap == null)
|
||
{
|
||
LogSystem.LogError("RenderUpdateCityInfo Main.MapData missing player/city/grid data");
|
||
return;
|
||
}
|
||
|
||
//更新图标
|
||
InstantUpdateCityLabels();
|
||
|
||
//更新info底色
|
||
var selfPlayer = _mapData.PlayerMap?.SelfPlayerData;
|
||
_cityInfoMono?.SetBG(_cityData.Player(_mapData) == selfPlayer);
|
||
|
||
//更新人口条,会自动处理不在视野的情况
|
||
RenderUpdateCityPops(_cityData.Level,_cityData.LevelExp);
|
||
//更新GDP,会自动处理不在视野的情况
|
||
RenderUpdateCityCoinTechCulture();
|
||
//更新城市名,会自动处理不在视野的情况
|
||
RenderUpdateCityName();
|
||
|
||
//更新显示情况
|
||
var selfSight = selfPlayer?.Sight;
|
||
var cityGrid = _cityData.Grid(_mapData);
|
||
_cityInfoMono?.gameObject.SetActive(selfSight?.SightGidSet != null && selfSight.CheckIsInSight(cityGrid?.Id ?? 0));
|
||
|
||
}
|
||
|
||
|
||
|
||
private void GetEmbassyIconStatus(out bool showEmbassy,out bool showWarEmbassy)
|
||
{
|
||
showWarEmbassy = false;
|
||
showEmbassy = false;
|
||
//如果是对方的cradleCaptain,并且真人玩家在此建立了大使馆,才显示
|
||
if (!_cityData.Player(Main.MapData, out var player)) return;
|
||
//如果不是对方城市 return
|
||
if (player == Main.MapData.PlayerMap.SelfPlayerData) return;
|
||
//如果不是cradlecity return
|
||
if (!Main.CityLogic.CheckCradleCapital(_mapData, _cityData.Player(Main.MapData), _cityData)) return;
|
||
//如果没有建立大使馆,return
|
||
if (!Main.MapData.PlayerMap.SelfPlayerData.GetCountryDiplomacyInfo(player.Id, out var dipInfo)) return;
|
||
if (!dipInfo.IsEmbassy) return;
|
||
if (dipInfo.DiplomacyState == DiplomacyState.War)
|
||
showWarEmbassy = true;
|
||
else showEmbassy = true;
|
||
}
|
||
private void RenderUpdateCityCoinTech()
|
||
{
|
||
//如果不是己方的城市,有外交才显示,不然不显示
|
||
if (!(_cityData.Player(Main.MapData)?.IsSelfPlayer() ?? true))
|
||
{
|
||
//处理外交金钱
|
||
var coin = Main.PlayerLogic.GetEmbassyCoin(_mapData,_mapData.PlayerMap.SelfPlayerData,_cityData.Player(Main.MapData));
|
||
bool hasEmbassyCoin = coin > 0 &&
|
||
Main.CityLogic.CheckCradleCapital(_mapData, _cityData.Player(Main.MapData),
|
||
_cityData);
|
||
_cityInfoMono?.SetCoin(hasEmbassyCoin,coin);
|
||
_cityInfoMono?.SetTech(false, 0);
|
||
_cityInfoMono?.SetCulture(false, 0);
|
||
return;
|
||
}
|
||
//如果是己方城市,直接显示
|
||
//被敌方单位站住的城市本回合不产出,UI显示0
|
||
if (Main.CityLogic.IsCityHeldByEnemyUnit(_mapData, _cityData))
|
||
{
|
||
_cityInfoMono?.SetCoin(true, 0);
|
||
_cityInfoMono?.SetTech(false, 0);
|
||
_cityInfoMono?.SetCulture(false, 0);
|
||
return;
|
||
}
|
||
_cityInfoMono?.SetCoin(true,Main.CityLogic.GetCityCoinPerTurn(_mapData,_cityData));
|
||
var tech = Main.CityLogic.GetCityTechPointPerTurn(_mapData, _cityData);
|
||
_cityInfoMono?.SetTech(tech > 0,tech);
|
||
var culture = Main.CityLogic.GetCityCulturePointPerTurn(_mapData, _cityData);
|
||
_cityInfoMono?.SetCulture(culture > 0,culture);
|
||
|
||
}
|
||
|
||
private void RenderUpdateCityCoinTechCulture()
|
||
{
|
||
//如果不是己方的城市,有外交才显示,不然不显示
|
||
if (!(_cityData.Player(Main.MapData)?.IsSelfPlayer() ?? true))
|
||
{
|
||
//处理外交金钱
|
||
var coin = Main.PlayerLogic.GetEmbassyCoin(_mapData,_mapData.PlayerMap.SelfPlayerData,_cityData.Player(Main.MapData));
|
||
bool hasEmbassyCoin = coin > 0 &&
|
||
Main.CityLogic.CheckCradleCapital(_mapData, _cityData.Player(Main.MapData),
|
||
_cityData);
|
||
_cityInfoMono?.SetCoin(hasEmbassyCoin,coin);
|
||
_cityInfoMono?.SetTech(false, 0);
|
||
_cityInfoMono?.SetCulture(false, 0);
|
||
return;
|
||
}
|
||
//如果是己方城市,直接显示
|
||
//被敌方单位站住的城市本回合不产出,UI显示0
|
||
if (Main.CityLogic.IsCityHeldByEnemyUnit(_mapData, _cityData))
|
||
{
|
||
_cityInfoMono?.SetCoin(true, 0);
|
||
_cityInfoMono?.SetTech(false, 0);
|
||
_cityInfoMono?.SetCulture(false, 0);
|
||
return;
|
||
}
|
||
_cityInfoMono?.SetCoin(true,Main.CityLogic.GetCityCoinPerTurn(_mapData,_cityData));
|
||
var tech = Main.CityLogic.GetCityTechPointPerTurn(_mapData, _cityData);
|
||
_cityInfoMono?.SetTech(tech > 0,tech);
|
||
var culture = Main.CityLogic.GetCityCulturePointPerTurn(_mapData, _cityData);
|
||
_cityInfoMono?.SetCulture(culture > 0,culture);
|
||
}
|
||
|
||
private void RenderUpdateCityName()
|
||
{
|
||
if (_cityData == null)
|
||
{
|
||
LogSystem.LogError("RenderUpdateCityName _cityData == null");
|
||
return;
|
||
}
|
||
|
||
var civDataAssets = Table.Instance?.CivDataAssets;
|
||
if (civDataAssets == null)
|
||
{
|
||
LogSystem.LogError("RenderUpdateCityName Table.Instance?.CivDataAssets == null");
|
||
return;
|
||
}
|
||
|
||
if (!civDataAssets.GetCityInfo(_cityData.Name,out var cityInfo) || cityInfo == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityName cityInfo == null, cityName={_cityData.Name}");
|
||
return;
|
||
}
|
||
|
||
_cityInfoMono?.SetCityName(cityInfo.CityName);
|
||
|
||
}
|
||
|
||
private int GetCityPopulationSafe(MapData mapData, uint cityId)
|
||
{
|
||
int ret = 0;
|
||
if (mapData?.UnitMap?.UnitList == null || mapData.UnitToCityDict == null)
|
||
{
|
||
LogSystem.LogError("GetCityPopulationSafe mapData?.UnitMap?.UnitList == null || mapData.UnitToCityDict == null");
|
||
return ret;
|
||
}
|
||
|
||
foreach (var unit in mapData.UnitMap.UnitList)
|
||
{
|
||
if (unit == null)
|
||
{
|
||
LogSystem.LogError($"GetCityPopulationSafe unit == null, cityId={cityId}");
|
||
continue;
|
||
}
|
||
|
||
if (!mapData.UnitToCityDict.TryGetValue(unit.Id, out var unitCityId) || unitCityId != cityId)
|
||
continue;
|
||
|
||
bool noPopulation = false;
|
||
if (unit.Skills == null)
|
||
{
|
||
LogSystem.LogError($"GetCityPopulationSafe unit.Skills == null, unitId={unit.Id}");
|
||
}
|
||
else
|
||
{
|
||
foreach (var skill in unit.Skills)
|
||
{
|
||
if (skill?.GetSkillType() != SkillType.NOPOPULATION) continue;
|
||
noPopulation = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!noPopulation)
|
||
ret++;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
private void RenderUpdateCityPops(int level,int levelExp)
|
||
{
|
||
var mapData = _mapData;
|
||
if (mapData?.PlayerMap == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops mapData?.PlayerMap == null");
|
||
return;
|
||
}
|
||
|
||
var selfPlayer = mapData.PlayerMap.SelfPlayerData;
|
||
if (selfPlayer?.Sight?.SightGidSet == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops selfPlayer?.Sight?.SightGidSet == null");
|
||
return;
|
||
}
|
||
if (_cityData == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops _cityData == null");
|
||
return;
|
||
}
|
||
|
||
if (mapData.CityToGridDict == null || mapData.GridMap == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops mapData.CityToGridDict == null || mapData.GridMap == null");
|
||
return;
|
||
}
|
||
|
||
if (mapData.CityToPlayerDict == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops mapData.CityToPlayerDict == null");
|
||
return;
|
||
}
|
||
|
||
if (mapData.UnitMap?.UnitList == null || mapData.UnitToCityDict == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops mapData.UnitMap?.UnitList == null || mapData.UnitToCityDict == null");
|
||
return;
|
||
}
|
||
|
||
if (!mapData.GetGridDataByCityId(_cityData.Id, out var cityGrid) || cityGrid == null)
|
||
{
|
||
LogSystem.LogError($"RenderUpdateCityPops cityGrid == null, cityId={_cityData.Id}");
|
||
return;
|
||
}
|
||
|
||
if (!selfPlayer.Sight.CheckIsInSight(cityGrid.Id))
|
||
return;
|
||
|
||
//如果不是己方的城市,不显示
|
||
var cityPlayer = _cityData.Player(mapData);
|
||
bool isSelfCity = cityPlayer?.Id == selfPlayer.Id;
|
||
|
||
//Step 3 设置城市经验条
|
||
_cityInfoMono?.SetLevelBar(isSelfCity,level,levelExp,GetCityPopulationSafe(mapData, _cityData.Id));
|
||
|
||
//Step 4 更新cityName
|
||
RenderUpdateCityName();
|
||
}
|
||
|
||
|
||
public void UpdateLevelShow(int level,int levelExp)
|
||
{
|
||
RenderUpdateCityPops(level, levelExp);
|
||
}
|
||
|
||
public uint GetCid()
|
||
{
|
||
return _cityId;
|
||
}
|
||
|
||
|
||
/*public void RenderUpdateDebug()
|
||
{
|
||
if (DebugCenter.Instance.DebugMode)
|
||
{
|
||
if(!_RODebugText.activeSelf)
|
||
_RODebugText.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
_RODebugText.SetActive(false);
|
||
return;
|
||
}
|
||
_debugText.text = "";
|
||
_debugText.text += $"CID={_cityId} PID={_cityData.Player(Main.MapData)?.Id ?? 0} CIV={_cityData.Player(Main.MapData)?.PlayerCivId ?? 0} gold={_cityData.Player(Main.MapData)?.PlayerCoin ?? 0}\n";
|
||
//如果不是我方单位,显示city和player的战略
|
||
if(!_mapData.CheckCityIdBelongPlayerId(_cityId,_mapData.PlayerMap.SelfPlayerData.Id))
|
||
if (MainEditor.Instance.Data != null)
|
||
{
|
||
MainEditor.Instance.GetCityStrategy(_cityId, out var cst);
|
||
MainEditor.Instance.GetPlayerStrategy(_cityData.Player(Main.MapData)?.Id ?? 0, out var pst, out var target);
|
||
_debugText.text += $"CST={cst} PST={pst}";
|
||
_debugText.text += "\n";
|
||
}
|
||
|
||
//如果是首都,展示科技
|
||
if (_cityData.IsCapital)
|
||
{
|
||
_debugText.text += "tech={";
|
||
foreach (var tech in _cityData.Player(Main.MapData).TechTree.TechSet)
|
||
{
|
||
_debugText.text += tech + ",";
|
||
}
|
||
_debugText.text += "}\n";
|
||
}
|
||
|
||
|
||
//如果是不我方单位,展示city上一回合的action list
|
||
if(!_mapData.CheckCityIdBelongPlayerId(_cityId,_mapData.PlayerMap.SelfPlayerData.Id))
|
||
if (MainEditor.Instance.Data != null)
|
||
{
|
||
var actionList = MainEditor.Instance.GetCityActions(_cityId);
|
||
_debugText.text += $"Turn {_cityData.Player(Main.MapData)?.Turn} act list\n";
|
||
if(actionList != null)
|
||
foreach (var act in actionList)
|
||
_debugText.text += act.DebugInfo() + "\n";
|
||
}
|
||
}*/
|
||
|
||
|
||
}
|
||
}
|