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 spawnedCardRoots = new List(); private readonly List spawnedCardBasePositions = new List(); private Sequence allySlotEntrySequence; /// /// 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. /// 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(); if (rectTransform != null) { if (!UI_OrderedEntryAnimator.IsLayoutSensitive(rectTransform)) { 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(); 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(); 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; bool canMove = !UI_OrderedEntryAnimator.IsLayoutSensitive(rt); if (canMove) { rt.anchoredPosition = new Vector2(basePos.x + offsetX, basePos.y); } float startAt = i * stagger; // top -> bottom (sibling order) if (canMove) 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) { if (!UI_OrderedEntryAnimator.IsLayoutSensitive(rt)) rt.anchoredPosition = spawnedCardBasePositions[i]; } SetCanvasAlpha(rt.transform, 1f); } } /// /// Documentation text normalized. /// /// 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 validCards = new List(); // 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(); if (cg == null) cg = root.gameObject.AddComponent(); return cg; } private static void SetCanvasAlpha(Transform root, float alpha) { CanvasGroup cg = GetOrAddCanvasGroup(root); if (cg == null) return; cg.alpha = Mathf.Clamp01(alpha); } }