770 lines
25 KiB
C#
770 lines
25 KiB
C#
using System.Collections.Generic;
|
||
using Logic;
|
||
using Logic.Action;
|
||
using Logic.Audio;
|
||
using Logic.CrashSight;
|
||
using Logic.Multilingual;
|
||
using RuntimeData;
|
||
using TH1_Core.Events;
|
||
using TH1_Core.Managers;
|
||
using TH1_Logic.Action;
|
||
using TH1_Logic.Core;
|
||
using TH1_UI.Components;
|
||
using TH1_UI.HintUI;
|
||
using TMPro;
|
||
using UI.HintUI;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TH1_UI.View.Info
|
||
{
|
||
public class UIInfoDiplomacyView : Base.View
|
||
{
|
||
public Button closeButton;
|
||
public Button BlockButton;
|
||
public RectTransform VerticalGroup;
|
||
|
||
// Avatar部分
|
||
public TextMeshProUGUI ForceTitle;
|
||
public RectTransform ForceTitleRect;
|
||
public Image LeaderAvatar;
|
||
public RectTransform BubbleChat;
|
||
public TextMeshProUGUI BubbleChatText;
|
||
public Image TopStripeBG2;
|
||
public Image TopStripeBG;
|
||
public Image ForceTitleBG;
|
||
|
||
// Status部分
|
||
public Transform StatusArea;
|
||
public GameObject Status;
|
||
public Image StateIcon;
|
||
public TextMeshProUGUI StateText;
|
||
public RectTransform Title_Status;
|
||
|
||
//态度条
|
||
public GameObject AttitudeArea;
|
||
public TextMeshProUGUI AttitudeNoMeetText;
|
||
public RectTransform RelationHandle;
|
||
public GameObject AttitudeBar;
|
||
public HintTrigger AttitudeBarHint;
|
||
|
||
|
||
//ActionArea
|
||
|
||
public Transform ActionArea;
|
||
|
||
public Image AllyActionCircleBGOutside;
|
||
public Image AllyActionCircleBG;
|
||
public GameObject AllyActionSend;
|
||
public Button AllyActionButton;
|
||
|
||
public Image EmbassyActionCircleBGOutside;
|
||
public Image EmbassyActionCircleBG;
|
||
public Image EmbassyActionCost;
|
||
public TextMeshProUGUI EmbassyActionCostText;
|
||
public Button EmbassyActionButton;
|
||
|
||
public GameObject BreakAllyAction;
|
||
public Button BreakAllyActionButton;
|
||
|
||
private GameObject _robAction;
|
||
private Image _robActionCircleBGOutside;
|
||
private Image _robActionCircleBG;
|
||
private GameObject _robActionSend;
|
||
private Button _robActionButton;
|
||
private Image _robActionIcon;
|
||
private TextMeshProUGUI _robActionTitle;
|
||
private HintTrigger _robActionHint;
|
||
private Image _robActionCost;
|
||
private TextMeshProUGUI _robActionCostText;
|
||
private GameObject _robActionTime;
|
||
private TextMeshProUGUI _robActionTimeText;
|
||
|
||
|
||
//RelationArea
|
||
// 动态池:根据敌方数量按需 Instantiate,复用已有实例
|
||
public GameObject UIInfoDiplomacyAvatarPrefab; // 拖入 UIInfoDiplomacyAvatar.prefab
|
||
public RectTransform RelationAvatarContainer; // Avatar 的父容器(带 LayoutGroup)
|
||
private List<UIInfoDiplomacyAvatarMono> _relationAvatarPool = new List<UIInfoDiplomacyAvatarMono>();
|
||
public ViDelegateAssisstant.Dele OnBtnCloseClick;
|
||
public GameObject RelationNoMeetHint;
|
||
|
||
|
||
public Sprite BlueBG;
|
||
public Sprite GrayBG;
|
||
public Sprite GreenBG;
|
||
public Color GrayColor;
|
||
public Color GreenColor;
|
||
public Color BlueColor;
|
||
public Color RedColor;
|
||
public Color BlueTextColor;
|
||
public Color RedTextColor;
|
||
|
||
|
||
protected override void OnInit()
|
||
{
|
||
base.OnInit();
|
||
closeButton.onClick.RemoveAllListeners();
|
||
BlockButton.onClick.RemoveAllListeners();
|
||
closeButton.onClick.AddListener(() => { OnBtnCloseClick.Invoke(); });
|
||
BlockButton.onClick.AddListener(() => { OnBtnCloseClick.Invoke(); });
|
||
}
|
||
|
||
public void SetContent(uint pid)
|
||
{
|
||
|
||
if (!Main.MapData.PlayerMap.GetPlayerDataByPlayerID(pid, out var player)) return;
|
||
if (!Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var info)) return;
|
||
var selfp = Main.MapData.PlayerMap.SelfPlayerData;
|
||
player.GetCountryDiplomacyInfo(selfp.Id, out var dipInfo);
|
||
|
||
|
||
//step #1 设置AvatarArea和chatBubble
|
||
SetContentAvatarArea(player);
|
||
|
||
//Step #2 设置StatusAcrea
|
||
SetContentStatusArea(player);
|
||
|
||
//Step #3 设置AttitudeArea
|
||
SetContentAttitudeArea(player);
|
||
|
||
//Step #4
|
||
SetContentActionArea(player);
|
||
|
||
//Step #5 设置该玩家和其他玩家的关系
|
||
SetContentRelationArea(player);
|
||
|
||
//Step #6 设置BGM
|
||
AudioManager.Instance.PlayMusic(info.MusicName,1f,2f,true);
|
||
|
||
//Step #7 重新排布:子元素先 rebuild,父容器 VerticalGroup 再整体 rebuild
|
||
if (Title_Status != null)
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(Title_Status);
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(VerticalGroup);
|
||
}
|
||
|
||
|
||
private void SetContentAvatarArea(PlayerData player)
|
||
{
|
||
bool isSelf = (player.Id == Main.MapData.PlayerMap.SelfPlayerData.Id);
|
||
var titleText = isSelf ? Table.Instance.DiplomacyDataAssets.DiplomacyUITitleSelf:Table.Instance.DiplomacyDataAssets.DiplomacyUITitle;
|
||
if (!Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var info)) return;
|
||
var forceName = Logic.PlayerLogic.GetDisplayForceName(Main.MapData, player);
|
||
MultilingualManager.Instance.SetUIText(ForceTitle,titleText,new List<string>{forceName});
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(ForceTitleRect);
|
||
LeaderAvatar.sprite = info.LeaderAvatar;
|
||
|
||
//设置color
|
||
var color2 = info.Color;
|
||
color2.a = 0.4f;
|
||
TopStripeBG2.color = color2;
|
||
TopStripeBG.color = info.Color;
|
||
ForceTitleBG.color = info.Color;
|
||
|
||
if (isSelf)
|
||
{
|
||
BubbleChat.gameObject.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
player.GetCountryDiplomacyInfo(Main.MapData.PlayerMap.SelfPlayerId, out var dipInfo);
|
||
bool meetus = dipInfo.DiplomacyState != DiplomacyState.NoDiplomacy;
|
||
if (!meetus)
|
||
{
|
||
BubbleChat.gameObject.SetActive(false);
|
||
return;
|
||
}
|
||
var chatText = Table.Instance.DiplomacyDataAssets.GetDiplomacyTextByFeeling((Forces)(player.PlayerForceId),dipInfo.FeelingState);
|
||
if (string.IsNullOrEmpty(chatText) || chatText == "0")
|
||
{
|
||
BubbleChat.gameObject.SetActive(false);
|
||
return;
|
||
}
|
||
BubbleChat.gameObject.SetActive(true);
|
||
MultilingualManager.Instance.SetUIText(BubbleChatText, chatText);
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(BubbleChat);
|
||
}
|
||
|
||
private void SetContentStatusArea(PlayerData player)
|
||
{
|
||
bool isSelf = (player.Id == Main.MapData.PlayerMap.SelfPlayerData.Id);
|
||
StatusArea.gameObject.SetActive(!isSelf);
|
||
if (isSelf) return;
|
||
|
||
if (!player.GetCountryDiplomacyInfo(Main.MapData.PlayerMap.SelfPlayerId, out var dipInfo)) return;
|
||
if (!Table.Instance.DiplomacyDataAssets.GetStateInfo(dipInfo.DiplomacyState, out var stateInfo)) return;
|
||
|
||
bool meetus = dipInfo.DiplomacyState != DiplomacyState.NoDiplomacy;
|
||
Status.gameObject.SetActive(meetus);
|
||
|
||
StateIcon.color = stateInfo.StateColor;
|
||
StateIcon.sprite = stateInfo.StateIcon;
|
||
MultilingualManager.Instance.SetUIText(StateText,stateInfo.StateText);
|
||
}
|
||
|
||
private void SetContentAttitudeArea(PlayerData player)
|
||
{
|
||
bool isSelf = (player.Id == Main.MapData.PlayerMap.SelfPlayerData.Id);
|
||
AttitudeArea.gameObject.SetActive(!isSelf);
|
||
if (isSelf) return;
|
||
|
||
if (!player.GetCountryDiplomacyInfo(Main.MapData.PlayerMap.SelfPlayerId, out var dipInfo)) return;
|
||
|
||
bool meetus = dipInfo.DiplomacyState != DiplomacyState.NoDiplomacy;
|
||
AttitudeNoMeetText.gameObject.SetActive(!meetus);
|
||
AttitudeBar.SetActive(meetus);
|
||
if(!meetus) return;
|
||
|
||
RelationHandle.anchoredPosition = new Vector2(Mathf.Lerp(13f, 585f, dipInfo.FeelingValue/100f),RelationHandle.anchoredPosition.y);
|
||
|
||
|
||
var text = $"<color=yellow>" + MultilingualManager.Instance.GetMultilingualTextSafe(Table.Instance.TextDataAssets.PresentationUIDiplomacyThinkYouText) +"</color><br>";
|
||
foreach (var op in dipInfo.FeelingStrategyList)
|
||
{
|
||
if (!Table.Instance.DiplomacyDataAssets.GetFeelingStragegyInfo(op, out var stgInfo)) continue;
|
||
text += $"<color=#{ColorUtility.ToHtmlStringRGB(stgInfo.FeelingStrategyColor)}>";
|
||
text += MultilingualManager.Instance.GetMultilingualTextSafe(stgInfo.FeelingStrategyTitle);
|
||
text += "</color>:";
|
||
text += MultilingualManager.Instance.GetMultilingualTextSafe(stgInfo.FeelingStrategyDesc);
|
||
text += "<br>";
|
||
}
|
||
|
||
AttitudeBarHint.DataProvider.HintDataType = HintDataType.TextData;
|
||
AttitudeBarHint.DataProvider.Text = text;
|
||
|
||
}
|
||
|
||
|
||
private void SetContentActionArea(PlayerData player)
|
||
{
|
||
bool isSelf = (player.Id == Main.MapData.PlayerMap.SelfPlayerData.Id);
|
||
ActionArea.gameObject.SetActive(!isSelf);
|
||
if (isSelf) return;
|
||
|
||
HideRobActionIfBound();
|
||
|
||
if (!player.GetCountryDiplomacyInfo(Main.MapData.PlayerMap.SelfPlayerId, out var dipInfo)) return;
|
||
|
||
SetAllyAction(player);
|
||
SetEmbassyAction(player);
|
||
SetBreakAllyAction(player);
|
||
SetRobAction(player);
|
||
}
|
||
|
||
|
||
private void SetAllyAction(PlayerData player)
|
||
{
|
||
if (player == null)
|
||
{
|
||
LogSystem.LogError("SetAllyAction Error: player is null");
|
||
return;
|
||
}
|
||
|
||
var actionId = new CommonActionId()
|
||
{ ActionType = CommonActionType.PlayerAction, PlayerActionType = PlayerActionType.OfferAlly};
|
||
|
||
var actionParams = new CommonActionParams(
|
||
mapData: Main.MapData,
|
||
playerData: Main.MapData.PlayerMap.SelfPlayerData,
|
||
targetPlayer:player,
|
||
mainObjectType: MainObjectType.Player);
|
||
|
||
var action = ActionLogicFactory.GetActionLogic(actionId);
|
||
|
||
// 检查 action 是否为 null
|
||
if (action == null)
|
||
{
|
||
LogSystem.LogError("SetAllyAction Error: action is null");
|
||
return;
|
||
}
|
||
|
||
// 检查 UI 组件
|
||
if (AllyActionButton == null || AllyActionCircleBGOutside == null || AllyActionCircleBG == null || AllyActionSend == null)
|
||
{
|
||
LogSystem.LogError($"SetAllyAction Error: UI Component is null. AllyActionButton={AllyActionButton}, AllyActionCircleBGOutside={AllyActionCircleBGOutside}, AllyActionCircleBG={AllyActionCircleBG}, AllyActionSend={AllyActionSend}");
|
||
return;
|
||
}
|
||
|
||
if (!action.CheckShow(actionParams, out var actionCantType)) return;
|
||
|
||
AllyActionButton.onClick.RemoveAllListeners();
|
||
switch (actionCantType)
|
||
{
|
||
case ShowType.Locked:
|
||
|
||
AllyActionCircleBGOutside.color = GrayColor;
|
||
AllyActionCircleBG.sprite = GrayBG;
|
||
AllyActionSend.gameObject.SetActive(false);
|
||
break;
|
||
case ShowType.None:
|
||
AllyActionCircleBGOutside.color = BlueColor;
|
||
AllyActionCircleBG.sprite = BlueBG;
|
||
AllyActionSend.gameObject.SetActive(false);
|
||
AllyActionButton.onClick.AddListener(() =>
|
||
{
|
||
//只有轮到我行动的时候,点击才生效
|
||
if (actionParams.MapData?.CurPlayer != null &&
|
||
actionParams.MapData.CurPlayer == Main.MapData?.PlayerMap?.SelfPlayerData)
|
||
{
|
||
action.CompleteExecute(actionParams);
|
||
//EventManager.Publish(new HideUIInfoDiplomacy(){non = 0});
|
||
//TODO 莫名其妙的bug publish Hide 不生效, 强制Close才生效
|
||
OnBtnCloseClick?.Invoke();
|
||
}
|
||
|
||
});
|
||
break;
|
||
case ShowType.Send:
|
||
AllyActionCircleBGOutside.color = BlueColor;
|
||
AllyActionCircleBG.sprite = BlueBG;
|
||
AllyActionSend.gameObject.SetActive(true);
|
||
break;
|
||
case ShowType.Done:
|
||
AllyActionCircleBGOutside.color = GreenColor;
|
||
AllyActionCircleBG.sprite = GreenBG;
|
||
AllyActionSend.gameObject.SetActive(false);
|
||
break;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
private void SetEmbassyAction(PlayerData player)
|
||
{
|
||
if (player == null)
|
||
{
|
||
LogSystem.LogError($"SetEmbassyAction Error player is null");
|
||
return;
|
||
}
|
||
|
||
var actionId = new CommonActionId()
|
||
{ ActionType = CommonActionType.PlayerAction, PlayerActionType = PlayerActionType.Embassy};
|
||
var actionParams = new CommonActionParams(
|
||
mapData: Main.MapData,
|
||
playerData: Main.MapData.PlayerMap.SelfPlayerData,
|
||
targetPlayer:player,
|
||
mainObjectType: MainObjectType.Player);
|
||
|
||
var action = ActionLogicFactory.GetActionLogic(actionId);
|
||
if (action == null)
|
||
{
|
||
LogSystem.LogError($"SetEmbassyAction Error Action is null");
|
||
return;
|
||
}
|
||
if (!action.CheckShow(actionParams, out var actionCantType)) return;
|
||
|
||
if (!EmbassyActionButton || !EmbassyActionCircleBGOutside || !EmbassyActionCircleBG || !EmbassyActionCost ||
|
||
!EmbassyActionCostText || OnBtnCloseClick == null)
|
||
{
|
||
LogSystem.LogError($"SetEmbassyAction Error UI Component is null " +
|
||
$"{EmbassyActionButton} {EmbassyActionCircleBGOutside} {EmbassyActionCircleBG} " +
|
||
$"{EmbassyActionCost} {EmbassyActionCostText} {OnBtnCloseClick}");
|
||
return;
|
||
}
|
||
EmbassyActionButton.onClick.RemoveAllListeners();
|
||
|
||
switch (actionCantType)
|
||
{
|
||
case ShowType.Locked:
|
||
|
||
EmbassyActionCircleBGOutside.color = GrayColor;
|
||
EmbassyActionCircleBG.sprite = GrayBG;
|
||
EmbassyActionCost.gameObject.SetActive(false);
|
||
|
||
break;
|
||
case ShowType.None:
|
||
EmbassyActionCircleBGOutside.color = BlueColor;
|
||
EmbassyActionCircleBG.sprite = BlueBG;
|
||
EmbassyActionCost.gameObject.SetActive(true);
|
||
EmbassyActionCostText.color = BlueTextColor;
|
||
EmbassyActionButton.onClick.AddListener(() =>
|
||
{
|
||
//只有轮到我行动的时候,点击才生效
|
||
if (actionParams.MapData.CurPlayer != null &&
|
||
actionParams.MapData.CurPlayer == Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
action.CompleteExecute(actionParams);
|
||
//EventManager.Publish(new HideUIInfoDiplomacy(){non =0});
|
||
//TODO 莫名其妙的bug publish Hide 不生效, 强制Close才生效
|
||
OnBtnCloseClick?.Invoke();
|
||
}
|
||
|
||
});
|
||
break;
|
||
case ShowType.Cost:
|
||
EmbassyActionCircleBGOutside.color = RedColor;
|
||
EmbassyActionCircleBG.sprite = BlueBG;
|
||
EmbassyActionCost.gameObject.SetActive(true);
|
||
EmbassyActionCostText.color = RedTextColor;
|
||
break;
|
||
case ShowType.Done:
|
||
EmbassyActionCircleBGOutside.color = GreenColor;
|
||
EmbassyActionCircleBG.sprite = GreenBG;
|
||
EmbassyActionCost.gameObject.SetActive(false);
|
||
break;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
private void SetBreakAllyAction(PlayerData player)
|
||
{
|
||
if (player == null)
|
||
{
|
||
LogSystem.LogError("SetBreakAllyAction Error: player is null");
|
||
return;
|
||
}
|
||
|
||
var actionId = new CommonActionId()
|
||
{ ActionType = CommonActionType.PlayerAction, PlayerActionType = PlayerActionType.BreakAlly};
|
||
|
||
var actionParams = new CommonActionParams(
|
||
mapData: Main.MapData,
|
||
playerData: Main.MapData.PlayerMap.SelfPlayerData,
|
||
targetPlayer:player,
|
||
mainObjectType: MainObjectType.Player);
|
||
|
||
var action = ActionLogicFactory.GetActionLogic(actionId);
|
||
// 检查 action 是否为 null
|
||
if (action == null)
|
||
{
|
||
LogSystem.LogError("SetBreakAllyAction Error: action is null");
|
||
return;
|
||
}
|
||
|
||
// 检查 UI 组件
|
||
if (BreakAllyAction == null || BreakAllyActionButton == null)
|
||
{
|
||
LogSystem.LogError($"SetBreakAllyAction Error: UI Component is null. BreakAllyAction={BreakAllyAction}, BreakAllyActionButton={BreakAllyActionButton}");
|
||
return;
|
||
}
|
||
|
||
bool canShow = action.CheckShow(actionParams, out var actionCantType);
|
||
BreakAllyAction.gameObject.SetActive(canShow);
|
||
BreakAllyActionButton.onClick.RemoveAllListeners();
|
||
if (!canShow) return;
|
||
BreakAllyActionButton.onClick.AddListener(() =>
|
||
{
|
||
//只有轮到我行动的时候,点击才生效
|
||
if (actionParams.MapData.CurPlayer != null && actionParams.MapData.CurPlayer == Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
action.CompleteExecute(actionParams);
|
||
//TODO 莫名其妙的bug publish Hide 不生效, 强制Close才生效 _task居然=空 导致无法关闭
|
||
//EventManager.Publish(new HideUIInfoDiplomacy());
|
||
|
||
OnBtnCloseClick?.Invoke();
|
||
}
|
||
});
|
||
}
|
||
|
||
private void HideRobActionIfBound()
|
||
{
|
||
if (_robAction == null && ActionArea != null)
|
||
{
|
||
_robAction = ActionArea.Find("RobAction")?.gameObject;
|
||
}
|
||
|
||
if (_robAction != null) _robAction.SetActive(false);
|
||
}
|
||
|
||
private void SetRobAction(PlayerData player)
|
||
{
|
||
if (player == null)
|
||
{
|
||
LogSystem.LogError("SetRobAction Error: player is null");
|
||
return;
|
||
}
|
||
|
||
var actionId = new CommonActionId()
|
||
{ ActionType = CommonActionType.PlayerAction, PlayerActionType = PlayerActionType.DanegeldDemand };
|
||
|
||
var actionParams = new CommonActionParams(
|
||
mapData: Main.MapData,
|
||
playerData: Main.MapData.PlayerMap.SelfPlayerData,
|
||
targetPlayer: player,
|
||
mainObjectType: MainObjectType.Player);
|
||
|
||
var action = ActionLogicFactory.GetActionLogic(actionId);
|
||
if (action == null)
|
||
{
|
||
LogSystem.LogError("SetRobAction Error: action is null");
|
||
return;
|
||
}
|
||
|
||
if (!BindRobActionObject()) return;
|
||
|
||
bool canShow = action.CheckShow(actionParams, out var actionCantType);
|
||
if (!canShow)
|
||
{
|
||
_robAction.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
_robAction.SetActive(true);
|
||
_robActionButton.onClick.RemoveAllListeners();
|
||
if (_robActionSend != null) _robActionSend.SetActive(false);
|
||
var cost = action.GetCost(actionParams);
|
||
SetRobActionCost(cost, BlueTextColor, false);
|
||
SetRobActionCooldown(0, false);
|
||
|
||
SetRobActionInfo(actionId);
|
||
|
||
bool locked = !action.CheckCan(actionParams);
|
||
switch (actionCantType)
|
||
{
|
||
case ShowType.None:
|
||
SetRobActionVisual(BlueColor, BlueBG);
|
||
SetRobActionCost(cost, BlueTextColor, true);
|
||
if (!locked && CanLocalExecuteAction(actionParams))
|
||
{
|
||
_robActionButton.onClick.AddListener(() =>
|
||
{
|
||
if (!action.CheckCan(actionParams)) return;
|
||
if (!CanLocalExecuteAction(actionParams)) return;
|
||
if (action.CompleteExecute(actionParams))
|
||
OnBtnCloseClick?.Invoke();
|
||
});
|
||
}
|
||
break;
|
||
case ShowType.Send:
|
||
SetRobActionVisual(BlueColor, BlueBG);
|
||
if (_robActionSend != null) _robActionSend.SetActive(true);
|
||
break;
|
||
case ShowType.Done:
|
||
SetRobActionVisual(GreenColor, GreenBG);
|
||
break;
|
||
case ShowType.Cost:
|
||
SetRobActionVisual(RedColor, BlueBG);
|
||
SetRobActionCost(cost, RedTextColor, true);
|
||
break;
|
||
case ShowType.Cold:
|
||
locked = true;
|
||
SetRobActionVisual(GrayColor, GrayBG);
|
||
SetRobActionCost(cost,
|
||
actionParams.PlayerData != null && actionParams.PlayerData.PlayerCoin < cost
|
||
? RedTextColor
|
||
: BlueTextColor,
|
||
true);
|
||
SetRobActionCooldown(GetDanegeldCooldownTurns(actionParams), true);
|
||
break;
|
||
default:
|
||
SetRobActionVisual(GrayColor, GrayBG);
|
||
break;
|
||
}
|
||
|
||
SetRobActionHint(actionId, locked);
|
||
}
|
||
|
||
private bool BindRobActionObject()
|
||
{
|
||
if (ActionArea == null)
|
||
{
|
||
LogSystem.LogError("SetRobAction Error: ActionArea is null");
|
||
return false;
|
||
}
|
||
|
||
if (_robAction == null)
|
||
{
|
||
_robAction = ActionArea.Find("RobAction")?.gameObject;
|
||
}
|
||
|
||
if (_robAction == null)
|
||
{
|
||
LogSystem.LogError("SetRobAction Error: RobAction is not found under ActionArea");
|
||
return false;
|
||
}
|
||
|
||
var root = _robAction.transform;
|
||
var bg = FindChildRecursive(root, "BG");
|
||
var bg2 = FindChildRecursive(root, "BG2");
|
||
var icon = bg != null ? FindChildRecursive(bg, "Icon") : FindChildRecursive(root, "Icon");
|
||
var title = FindChildRecursive(root, "Title");
|
||
var cost = FindChildRecursive(root, "Cost");
|
||
var time = FindChildRecursive(root, "Time");
|
||
|
||
_robActionCircleBGOutside = bg2?.GetComponent<Image>();
|
||
_robActionCircleBG = bg?.GetComponent<Image>();
|
||
_robActionButton = bg?.GetComponent<Button>() ?? root.GetComponent<Button>();
|
||
_robActionHint = bg?.GetComponent<HintTrigger>() ?? root.GetComponent<HintTrigger>();
|
||
_robActionSend = bg != null ? FindChildRecursive(bg, "Send")?.gameObject : FindChildRecursive(root, "Send")?.gameObject;
|
||
_robActionIcon = icon?.GetComponent<Image>();
|
||
_robActionTitle = title?.GetComponent<TextMeshProUGUI>();
|
||
_robActionCost = cost?.GetComponent<Image>();
|
||
_robActionCostText = cost?.GetComponentInChildren<TextMeshProUGUI>(true);
|
||
_robActionTime = time?.gameObject;
|
||
_robActionTimeText = time?.GetComponentInChildren<TextMeshProUGUI>(true);
|
||
SetRobActionCost(0, BlueTextColor, false);
|
||
|
||
if (_robActionCircleBGOutside == null || _robActionCircleBG == null ||
|
||
_robActionButton == null || _robActionIcon == null || _robActionTitle == null)
|
||
{
|
||
LogSystem.LogError($"SetRobAction Error: UI Component is null. " +
|
||
$"BGOutside={_robActionCircleBGOutside}, BG={_robActionCircleBG}, " +
|
||
$"Button={_robActionButton}, Icon={_robActionIcon}, Title={_robActionTitle}");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private static Transform FindChildRecursive(Transform root, string childName)
|
||
{
|
||
if (root == null) return null;
|
||
if (root.name == childName) return root;
|
||
for (int i = 0; i < root.childCount; i++)
|
||
{
|
||
var found = FindChildRecursive(root.GetChild(i), childName);
|
||
if (found != null) return found;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private void SetRobActionInfo(CommonActionId actionId)
|
||
{
|
||
if (!Table.Instance.ActionDataAssets.GetActionInfo(actionId, out var info)) return;
|
||
|
||
var selfPlayer = Main.MapData.PlayerMap.SelfPlayerData;
|
||
var civ = selfPlayer.CivEnum;
|
||
var force = selfPlayer.ForceEnum;
|
||
SetActionInfoText(_robActionTitle, info.GetActionName(civ, force, GridSpType.None));
|
||
}
|
||
|
||
private void SetRobActionVisual(Color circleColor, Sprite bgSprite)
|
||
{
|
||
if (_robActionCircleBGOutside != null) _robActionCircleBGOutside.color = circleColor;
|
||
if (_robActionCircleBG != null) _robActionCircleBG.sprite = bgSprite;
|
||
}
|
||
|
||
private void SetRobActionCost(int cost, Color textColor, bool visible)
|
||
{
|
||
if (_robActionCost == null) return;
|
||
_robActionCost.gameObject.SetActive(visible && cost > 0);
|
||
if (_robActionCostText == null) return;
|
||
_robActionCostText.text = cost.ToString();
|
||
_robActionCostText.color = textColor;
|
||
}
|
||
|
||
private void SetRobActionCooldown(int turnCount, bool visible)
|
||
{
|
||
if (_robActionTime == null) return;
|
||
|
||
_robActionTime.SetActive(visible);
|
||
if (_robActionTimeText != null)
|
||
{
|
||
_robActionTimeText.text = Mathf.Max(1, turnCount).ToString();
|
||
_robActionTimeText.alignment = TextAlignmentOptions.Center;
|
||
_robActionTimeText.color = Color.white;
|
||
_robActionTimeText.fontSize = Mathf.Max(_robActionTimeText.fontSize, 20f);
|
||
}
|
||
}
|
||
|
||
private static int GetDanegeldCooldownTurns(CommonActionParams actionParams)
|
||
{
|
||
var player = actionParams?.PlayerData;
|
||
var targetPlayer = actionParams?.TargetPlayerData;
|
||
if (player == null || targetPlayer == null) return 0;
|
||
if (!player.GetCountryDiplomacyInfo(targetPlayer.Id, out var info) || info == null) return 0;
|
||
if (info.LastDanegeldDemandTurn == 0) return 0;
|
||
|
||
var cooldownEndTurn = (long)info.LastDanegeldDemandTurn + 2;
|
||
return Mathf.Max(0, (int)(cooldownEndTurn - player.Turn));
|
||
}
|
||
|
||
private void SetRobActionHint(CommonActionId actionId, bool locked)
|
||
{
|
||
if (_robActionHint == null || _robActionHint.DataProvider == null) return;
|
||
_robActionHint.DataProvider.HintDataType = HintDataType.ActionHintData;
|
||
_robActionHint.DataProvider.ActionIdData = actionId;
|
||
_robActionHint.DataProvider.locked = locked;
|
||
}
|
||
|
||
private static bool CanLocalExecuteAction(CommonActionParams actionParams)
|
||
{
|
||
return actionParams?.MapData?.CurPlayer != null
|
||
&& actionParams.PlayerData != null
|
||
&& actionParams.MapData.CurPlayer.Id == actionParams.PlayerData.Id
|
||
&& actionParams.MapData.CanLocalControlPlayer(actionParams.PlayerData.Id);
|
||
}
|
||
|
||
private static void SetActionInfoText(TextMeshProUGUI text, string value)
|
||
{
|
||
if (text == null) return;
|
||
if (uint.TryParse(value, out _))
|
||
{
|
||
MultilingualManager.Instance.SetUIText(text, value);
|
||
return;
|
||
}
|
||
|
||
var multilingual = text.GetComponent<MultilingualTextMono>();
|
||
if (multilingual != null) multilingual.ID = 0;
|
||
text.text = value ?? "";
|
||
}
|
||
|
||
private void SetContentRelationArea(PlayerData player)
|
||
{
|
||
if (UIInfoDiplomacyAvatarPrefab == null || RelationAvatarContainer == null)
|
||
{
|
||
LogSystem.LogError($"[UIInfoDiplomacyView] RelationArea 配置缺失: prefab={UIInfoDiplomacyAvatarPrefab}, container={RelationAvatarContainer}");
|
||
return;
|
||
}
|
||
|
||
//先全部隐藏,确保即使中途异常或跳过也不会残留上次的显示
|
||
for (int i = 0; i < _relationAvatarPool.Count; i++)
|
||
{
|
||
if (_relationAvatarPool[i] != null)
|
||
_relationAvatarPool[i].gameObject.SetActive(false);
|
||
}
|
||
|
||
int rk = 0;
|
||
//依次设置pid对她的每一个pid2的外交关系
|
||
foreach (var pid2 in player.MeetPlayers)
|
||
{
|
||
if (pid2 == player.Id) continue;
|
||
if(!Main.MapData.PlayerMap.GetPlayerDataByPlayerID(pid2,out var player2))continue;
|
||
if (!player2.IsSurvival) continue;
|
||
|
||
//双向 meet 状态可能不一致:A.MeetPlayers 包含 X,但 A.DiplomacyData 里还没 X 的外交项
|
||
//此时 dipInfo2=null,必须 continue 否则 NRE
|
||
if (!player.GetCountryDiplomacyInfo(pid2, out var dipInfo2) || dipInfo2 == null) continue;
|
||
if(!Table.Instance.DiplomacyDataAssets.GetStateInfo(dipInfo2.DiplomacyState, out var stateInfo2))continue;
|
||
|
||
var avatar = GetOrCreateRelationAvatar(rk);
|
||
if (avatar == null) continue;
|
||
avatar.gameObject.SetActive(true);
|
||
//设置名字、头像、外交状态
|
||
avatar.SetContent(player2, stateInfo2.DiplomacyState,
|
||
!Main.MapData.PlayerMap.SelfPlayerData.MeetPlayers.Contains(pid2));
|
||
rk++;
|
||
}
|
||
|
||
RelationNoMeetHint.SetActive(rk == 0);
|
||
}
|
||
|
||
// 池容量不足时扩容;返回指定索引位置的 Avatar 实例
|
||
private UIInfoDiplomacyAvatarMono GetOrCreateRelationAvatar(int index)
|
||
{
|
||
while (_relationAvatarPool.Count <= index)
|
||
{
|
||
var go = Instantiate(UIInfoDiplomacyAvatarPrefab, RelationAvatarContainer);
|
||
var mono = go.GetComponent<UIInfoDiplomacyAvatarMono>();
|
||
if (mono == null)
|
||
{
|
||
LogSystem.LogError($"[UIInfoDiplomacyView] UIInfoDiplomacyAvatarPrefab 缺少 UIInfoDiplomacyAvatarMono 组件");
|
||
Destroy(go);
|
||
return null;
|
||
}
|
||
_relationAvatarPool.Add(mono);
|
||
}
|
||
return _relationAvatarPool[index];
|
||
}
|
||
|
||
public void CloseView()
|
||
{
|
||
AudioManager.Instance.StopMusic();
|
||
Logic.Audio.AudioManager.Instance.ResumeBgmRotationIfEnabled();
|
||
}
|
||
}
|
||
|
||
}
|