449 lines
17 KiB
C#
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);
|
|
}
|
|
}
|