Files
bansonic_beta_main/Assets/scripts/Team/settileTeam/loadSettlementTeamPrefab.cs
T

449 lines
17 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
public class loadSettlementTeamPrefab : MonoBehaviour
{
[Header("Inspector")]
public ScoreManager sm;
public teamUIController tuic;
public GameManager gm;
[Header("Inspector")]
public GameObject settleTeamCardsPrefab;
public GameObject objectToPutdown;
[Header("Settlement Entry Animation")]
[SerializeField] private bool enableAllySlotEntryTween = true;
[SerializeField] private float allySlotEntryOffsetX = 240f;
[SerializeField] private float allySlotEntryDuration = 0.35f;
[SerializeField] private float allySlotEntryStagger = 0.06f;
[SerializeField] private Ease allySlotEntryEase = Ease.OutCubic;
[SerializeField] private bool allySlotEntryUseUnscaledTime = true;
private readonly List<RectTransform> spawnedCardRoots = new List<RectTransform>();
private readonly List<Vector2> spawnedCardBasePositions = new List<Vector2>();
private Sequence allySlotEntrySequence;
/// <summary>
/// Instantiate five settlement cards under objectToPutdown and populate their fields.
/// Uses tuic.GetCurrentAllySOs() for profile/name when available, falls back to AllyHero_SO via allySlotIds.
/// Reads current HP from AllyCombatant instances named ally_01..ally_05 and idol score from ScoreManager.
/// </summary>
public void PopulateSettlementCards()
{
KillAllySlotEntrySequence();
spawnedCardRoots.Clear();
spawnedCardBasePositions.Clear();
if (settleTeamCardsPrefab == null)
{
Debug.LogWarning("loadSettlementTeamPrefab: prefab not assigned");
return;
}
// If objectToPutdown missing, fall back to this GameObject so instantiated cards are parented somewhere
if (objectToPutdown == null)
{
objectToPutdown = this.gameObject;
Debug.LogWarning($"loadSettlementTeamPrefab: objectToPutdown was null - falling back to '{objectToPutdown.name}'");
}
// ensure tuic reference
if (tuic == null && teamUIController.Instance != null)
tuic = teamUIController.Instance;
// Documentation text normalized.
if (sm == null && ScoreManager.Instance != null)
sm = ScoreManager.Instance;
// Diagnostic: log target parent state
bool parentSceneValid = objectToPutdown != null && objectToPutdown.scene.IsValid();
Debug.Log($"[loadSettlementTeamPrefab] Target parent: {objectToPutdown.name}, activeInHierarchy: {objectToPutdown.activeInHierarchy}, sceneValid: {parentSceneValid}");
// Documentation text normalized.
if (sm != null)
{
Debug.Log($"[loadSettlementTeamPrefab] ScoreManager found. Idol sums: R{sm.red_idolScore_sum} G{sm.green_idolScore_sum} Y{sm.yellow_idolScore_sum} P{sm.purple_idolScore_sum} B{sm.blue_idolScore_sum}");
}
else
{
Debug.LogWarning("[loadSettlementTeamPrefab] ScoreManager is null! Idol scores will be 0.");
}
// Clear existing children
for (int i = objectToPutdown.transform.childCount - 1; i >= 0; i--)
{
var c = objectToPutdown.transform.GetChild(i).gameObject;
#if UNITY_EDITOR
if (!Application.isPlaying) DestroyImmediate(c);
else
#endif
Destroy(c);
}
// Get current ally SOs if available
TeamCharacterDataInfo[] allySOs = null;
if (tuic != null)
allySOs = tuic.GetCurrentAllySOs();
for (int i = 0; i < 5; i++)
{
// Instantiate as UI child preserving local transform
var go = Instantiate(settleTeamCardsPrefab, objectToPutdown.transform, false);
if (go == null) continue;
go.SetActive(true);
// Ensure local scale/position are sane for UI
try { go.transform.localScale = Vector3.one; } catch { }
// Explicitly set parent and adjust RectTransform
go.transform.SetParent(objectToPutdown.transform, false);
var rectTransform = go.GetComponent<RectTransform>();
if (rectTransform != null)
{
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.sizeDelta = Vector2.zero;
spawnedCardRoots.Add(rectTransform);
}
// Diagnostic: verify parenting applied
if (go.transform.parent != objectToPutdown.transform)
{
Debug.LogWarning($"[loadSettlementTeamPrefab] Parenting mismatch for created card slot {i+1}: expected parent={objectToPutdown.name}, actual parent={go.transform.parent?.name}");
}
else
{
if (GameConfig.verboseLogs) Debug.Log($"[loadSettlementTeamPrefab] Card correctly parented under {objectToPutdown.name}");
}
var card = go.GetComponent<settleTeamPrefab>();
if (card == null)
{
Debug.LogWarning("Instantiated settleTeamCardsPrefab missing settleTeamPrefab component");
continue;
}
// Check if this slot is active and has an assigned hero
var ui = tuic ?? teamUIController.Instance;
bool isSlotActive = (ui != null) && ui.IsAllySlotActive(i);
int allyId = -1;
if (ui != null && ui.allySlotIds != null && i < ui.allySlotIds.Count)
allyId = ui.allySlotIds[i];
if (!isSlotActive || allyId <= 0)
{
card.SetEmptyState();
if (GameConfig.verboseLogs) Debug.Log($"[loadSettlementTeamPrefab] Slot {i + 1} is inactive or has no character (id={allyId}). Applied empty state.");
continue;
}
// Attempt to resolve an AllyHero_SO for this slot (via teamUIController.allySlotIds) so we can prefer its squareProfile
AllyHero_SO resolvedHeroSO = null;
if (allyId > 0)
{
var arr = RuntimeResourcesCache.LoadAllAllyHeroes();
foreach (var a in arr)
{
if (a != null && a.ally_heroID == allyId) { resolvedHeroSO = a; break; }
}
}
// Populate profile and name: prefer AllyHero_SO.ally_hero_settleDisplay when available
bool setProfile = false;
if (resolvedHeroSO != null && card.ally_profile != null)
{
if (resolvedHeroSO.ally_hero_settleDisplay != null)
{
card.ally_profile.sprite = resolvedHeroSO.ally_hero_settleDisplay;
card.ally_profile.color = new Color(1f, 1f, 1f, 1f);
if (card.ally_name != null)
{
string displayName = FormatAllyName(resolvedHeroSO.ally_heroDesignation, resolvedHeroSO.ally_heroName);
card.ally_name.text = displayName;
}
setProfile = true;
}
}
// Populate profile and name from TeamCharacterDataInfo if available (used by some UI flows)
if (!setProfile && allySOs != null && i < allySOs.Length && allySOs[i] != null)
{
var so = allySOs[i];
if (card.ally_profile != null && so.CharacterTeamSprite != null)
{
card.ally_profile.sprite = so.CharacterTeamSprite;
card.ally_profile.color = new Color(1f,1f,1f,1f);
}
if (card.ally_name != null) card.ally_name.text = so.CharacterName ?? string.Empty;
setProfile = true;
}
// Fallback: if we found an AllyHero_SO but it lacked squareProfile, try other profiles on the SO
if (!setProfile && resolvedHeroSO != null)
{
if (card.ally_profile != null && resolvedHeroSO.ally_heroProfile != null)
{
card.ally_profile.sprite = resolvedHeroSO.ally_heroProfile;
card.ally_profile.color = new Color(1f,1f,1f,1f);
}
if (card.ally_name != null)
{
string displayName = FormatAllyName(resolvedHeroSO.ally_heroDesignation, resolvedHeroSO.ally_heroName);
card.ally_name.text = displayName;
}
setProfile = true;
}
// Health: try to find AllyCombatant by name ally_01..ally_05
var allyGo = SceneObjectLookupCache.Find($"ally_0{i+1}");
if (allyGo != null)
{
var ac = allyGo.GetComponent<AllyCombatant>();
if (ac != null && card.ally_healthBar != null)
{
float fill = ac.maxHP > 0 ? (float)ac.currentHP / ac.maxHP : 0f;
card.ally_healthBar.fillAmount = Mathf.Clamp01(fill);
// Documentation text normalized.
if (ac.currentHP <= 0 && card.ally_profile != null && card.grayM != null)
{
card.ally_profile.material = card.grayM;
Debug.Log($"[loadSettlementTeamPrefab] Applied gray material to ally {i+1} (dead, currentHP={ac.currentHP})");
}
}
}
// this_allyIdolScore: map index to ScoreManager fields if available
// Documentation text normalized.
if (card.this_allyIdolScore != null)
{
int idol = 0;
// Documentation text normalized.
var scoreManager = sm != null ? sm : ScoreManager.Instance;
if (scoreManager != null)
{
switch (i)
{
case 0: idol = scoreManager.red_idolScore_sum; break;
case 1: idol = scoreManager.green_idolScore_sum; break;
case 2: idol = scoreManager.yellow_idolScore_sum; break;
case 3: idol = scoreManager.purple_idolScore_sum; break;
case 4: idol = scoreManager.blue_idolScore_sum; break;
}
Debug.Log($"[loadSettlementTeamPrefab] Slot {i+1} idol score: {idol}");
}
else
{
Debug.LogWarning($"[loadSettlementTeamPrefab] Cannot find ScoreManager for slot {i+1} idol score");
}
card.this_allyIdolScore.text = idol.ToString();
}
// Populate battle statistics from teamUIController
if (tuic != null)
{
if (card.this_allyDamageDealt != null)
card.this_allyDamageDealt.text = Mathf.FloorToInt(tuic.totalDamageDealt[i]).ToString();
if (card.this_allyDamageTook != null)
card.this_allyDamageTook.text = Mathf.FloorToInt(tuic.totalDamageTaken[i]).ToString();
if (card.this_allyHealthRestored != null)
card.this_allyHealthRestored.text = Mathf.FloorToInt(tuic.totalHealProvided[i]).ToString();
if (card.this_allyManaRestored != null)
card.this_allyManaRestored.text = Mathf.FloorToInt(tuic.totalManaRestored[i]).ToString();
}
if (GameConfig.verboseLogs) Debug.Log($"[loadSettlementTeamPrefab] Created card for slot {i+1}");
}
CaptureSpawnedCardBasePositions();
if (enableAllySlotEntryTween)
SetSpawnedCardsAlpha(0f);
}
public IEnumerator PlayAllySlotEntryBeforeMask()
{
if (!enableAllySlotEntryTween)
yield break;
CaptureSpawnedCardBasePositions();
if (spawnedCardRoots.Count == 0)
yield break;
KillAllySlotEntrySequence();
float duration = Mathf.Max(0.01f, allySlotEntryDuration);
float stagger = Mathf.Max(0f, allySlotEntryStagger);
float offsetX = allySlotEntryOffsetX;
allySlotEntrySequence = DOTween.Sequence().SetUpdate(allySlotEntryUseUnscaledTime);
for (int i = 0; i < spawnedCardRoots.Count; i++)
{
RectTransform rt = spawnedCardRoots[i];
if (rt == null) continue;
Vector2 basePos = spawnedCardBasePositions[i];
CanvasGroup group = GetOrAddCanvasGroup(rt.transform);
if (group != null) group.alpha = 0f;
rt.anchoredPosition = new Vector2(basePos.x + offsetX, basePos.y);
float startAt = i * stagger; // top -> bottom (sibling order)
allySlotEntrySequence.Insert(startAt, rt.DOAnchorPos(basePos, duration).SetEase(allySlotEntryEase).SetUpdate(allySlotEntryUseUnscaledTime));
if (group != null)
allySlotEntrySequence.Insert(startAt, group.DOFade(1f, duration).SetEase(allySlotEntryEase).SetUpdate(allySlotEntryUseUnscaledTime));
}
if (allySlotEntrySequence != null && allySlotEntrySequence.active)
yield return allySlotEntrySequence.WaitForCompletion();
allySlotEntrySequence = null;
}
public bool HasSpawnedCards()
{
if (!enableAllySlotEntryTween)
return false;
if (spawnedCardRoots.Count > 0)
return true;
return objectToPutdown != null && objectToPutdown.transform.childCount > 0;
}
public void ShowSpawnedCardsInstantly()
{
CaptureSpawnedCardBasePositions();
SetSpawnedCardsAlpha(1f);
}
public void CompleteAllySlotEntryImmediately()
{
CaptureSpawnedCardBasePositions();
KillAllySlotEntrySequence();
for (int i = 0; i < spawnedCardRoots.Count; i++)
{
RectTransform rt = spawnedCardRoots[i];
if (rt == null) continue;
if (i < spawnedCardBasePositions.Count)
rt.anchoredPosition = spawnedCardBasePositions[i];
SetCanvasAlpha(rt.transform, 1f);
}
}
/// <summary>
/// Documentation text normalized.
/// </summary>
/// Documentation text normalized.
/// Documentation text normalized.
/// Documentation text normalized.
private string FormatAllyName(string designation, string name)
{
if (string.IsNullOrWhiteSpace(designation))
{
return name ?? string.Empty;
}
if (string.IsNullOrWhiteSpace(name))
{
return designation;
}
return $"{designation} {name}";
}
private void OnDisable()
{
KillAllySlotEntrySequence();
}
private void CaptureSpawnedCardBasePositions()
{
if (objectToPutdown == null)
return;
Canvas.ForceUpdateCanvases();
RectTransform parentRt = objectToPutdown.transform as RectTransform;
if (parentRt != null)
LayoutRebuilder.ForceRebuildLayoutImmediate(parentRt);
List<RectTransform> validCards = new List<RectTransform>();
// Prefer freshly instantiated references from this run.
for (int i = 0; i < spawnedCardRoots.Count; i++)
{
RectTransform rt = spawnedCardRoots[i];
if (rt == null) continue;
if (rt.parent != objectToPutdown.transform) continue;
validCards.Add(rt);
}
// Fallback scan if cache is empty.
if (validCards.Count == 0)
{
Transform parent = objectToPutdown.transform;
for (int i = 0; i < parent.childCount; i++)
{
RectTransform rt = parent.GetChild(i) as RectTransform;
if (rt == null) continue;
validCards.Add(rt);
}
}
validCards.Sort((a, b) => a.GetSiblingIndex().CompareTo(b.GetSiblingIndex()));
spawnedCardRoots.Clear();
spawnedCardBasePositions.Clear();
for (int i = 0; i < validCards.Count; i++)
{
RectTransform rt = validCards[i];
spawnedCardRoots.Add(rt);
spawnedCardBasePositions.Add(rt.anchoredPosition);
SetCanvasAlpha(rt.transform, 1f);
}
}
private void SetSpawnedCardsAlpha(float alpha)
{
float clamped = Mathf.Clamp01(alpha);
for (int i = 0; i < spawnedCardRoots.Count; i++)
{
RectTransform rt = spawnedCardRoots[i];
if (rt == null) continue;
SetCanvasAlpha(rt.transform, clamped);
}
}
private void KillAllySlotEntrySequence()
{
if (allySlotEntrySequence == null)
return;
if (allySlotEntrySequence.active)
allySlotEntrySequence.Kill(false);
allySlotEntrySequence = null;
}
private static CanvasGroup GetOrAddCanvasGroup(Transform root)
{
if (root == null) return null;
CanvasGroup cg = root.GetComponent<CanvasGroup>();
if (cg == null) cg = root.gameObject.AddComponent<CanvasGroup>();
return cg;
}
private static void SetCanvasAlpha(Transform root, float alpha)
{
CanvasGroup cg = GetOrAddCanvasGroup(root);
if (cg == null) return;
cg.alpha = Mathf.Clamp01(alpha);
}
}