323 lines
8.7 KiB
C#
323 lines
8.7 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System.Runtime.ExceptionServices;
|
|
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
public class UI_Idols : MonoBehaviour
|
|
{
|
|
[Header("prefabs")]
|
|
public GameObject idolCardPrefab;
|
|
public Transform idolCardParent;
|
|
|
|
[Header("sprites")]
|
|
public Sprite[] idolLevelIcons;
|
|
public Sprite[] idolBtm;
|
|
|
|
[Header("colors")]
|
|
public Color[] idolSliderColors;
|
|
|
|
[Header("paths")]
|
|
public string idolSOpath_runtime;
|
|
public string idolSOpath_editor;
|
|
|
|
[Header("scan")]
|
|
public bool includeLockedHeroes = false;
|
|
|
|
[Header("rightPanel")]
|
|
public GameObject righePanel;
|
|
|
|
private readonly List<GameObject> spawnedCards = new List<GameObject>();
|
|
|
|
private void Start()
|
|
{
|
|
RebuildCards();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
RebuildCards();
|
|
}
|
|
|
|
[ContextMenu("Rebuild Idols")]
|
|
public void RebuildCards()
|
|
{
|
|
if (idolCardPrefab == null || idolCardParent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ClearCards();
|
|
|
|
List<AllyHero_SO> heroes = LoadHeroAssets();
|
|
if (heroes.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
heroes.Sort((left, right) => left.ally_heroID.CompareTo(right.ally_heroID));
|
|
|
|
for (int i = 0; i < heroes.Count; i++)
|
|
{
|
|
AllyHero_SO hero = heroes[i];
|
|
if (hero == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!includeLockedHeroes && !hero.isUnlocked)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
IdolLevelSnapshot snapshot = BuildLevelSnapshot(hero);
|
|
GameObject instance = Instantiate(idolCardPrefab, idolCardParent);
|
|
spawnedCards.Add(instance);
|
|
|
|
idolCardPrefab card = instance.GetComponent<idolCardPrefab>();
|
|
if (card == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
card.Setup(
|
|
hero.ally_hero_squareProfile,
|
|
hero.ally_heroDesignation,
|
|
hero.ally_heroName,
|
|
snapshot.sliderValue,
|
|
snapshot.xpText,
|
|
snapshot.levelIcon,
|
|
snapshot.bottomSprite,
|
|
snapshot.sliderColor);
|
|
}
|
|
}
|
|
|
|
private List<AllyHero_SO> LoadHeroAssets()
|
|
{
|
|
List<AllyHero_SO> heroes = new List<AllyHero_SO>();
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying && !string.IsNullOrWhiteSpace(idolSOpath_editor))
|
|
{
|
|
string[] searchFolders = { idolSOpath_editor };
|
|
string[] guids = AssetDatabase.FindAssets("t:AllyHero_SO", searchFolders);
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
AllyHero_SO hero = AssetDatabase.LoadAssetAtPath<AllyHero_SO>(assetPath);
|
|
if (hero != null)
|
|
{
|
|
heroes.Add(hero);
|
|
}
|
|
}
|
|
|
|
return heroes;
|
|
}
|
|
#endif
|
|
|
|
AllyHero_SO[] loadedHeroes = Resources.LoadAll<AllyHero_SO>(string.IsNullOrWhiteSpace(idolSOpath_runtime) ? string.Empty : idolSOpath_runtime);
|
|
for (int i = 0; i < loadedHeroes.Length; i++)
|
|
{
|
|
if (loadedHeroes[i] != null)
|
|
{
|
|
heroes.Add(loadedHeroes[i]);
|
|
}
|
|
}
|
|
|
|
return heroes;
|
|
}
|
|
|
|
private IdolLevelSnapshot BuildLevelSnapshot(AllyHero_SO hero)
|
|
{
|
|
IdolLevelSnapshot snapshot = new IdolLevelSnapshot
|
|
{
|
|
sliderValue = 0f,
|
|
xpText = "UNKNOWN",
|
|
levelIcon = GetLevelIconByIndex(4),
|
|
bottomSprite = GetBottomSpriteByIndex(4),
|
|
sliderColor = GetSliderColorByIndex(4)
|
|
};
|
|
|
|
if (hero == null)
|
|
{
|
|
return snapshot;
|
|
}
|
|
|
|
List<AllyHero_SO.AllyLevelInfo> levels = new List<AllyHero_SO.AllyLevelInfo>();
|
|
if (hero.levelStats != null)
|
|
{
|
|
for (int i = 0; i < hero.levelStats.Count; i++)
|
|
{
|
|
if (hero.levelStats[i] != null)
|
|
{
|
|
levels.Add(hero.levelStats[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (levels.Count == 0)
|
|
{
|
|
return snapshot;
|
|
}
|
|
|
|
levels.Sort((left, right) => left.requiredEXP.CompareTo(right.requiredEXP));
|
|
|
|
int currentExp = Mathf.Max(0, hero.ally_currentEXP);
|
|
int currentLevelIndex = -1;
|
|
for (int i = 0; i < levels.Count; i++)
|
|
{
|
|
if (currentExp >= levels[i].requiredEXP)
|
|
{
|
|
currentLevelIndex = i;
|
|
}
|
|
}
|
|
|
|
int displayIndex = Mathf.Clamp(currentLevelIndex >= 0 ? currentLevelIndex : 0, 0, levels.Count - 1);
|
|
AllyHero_SO.AllyLevelInfo currentLevel = levels[displayIndex];
|
|
int tierIndex = ResolveTierIndex(currentLevel, displayIndex, levels.Count);
|
|
snapshot.levelIcon = GetLevelIconByIndex(tierIndex);
|
|
snapshot.bottomSprite = GetBottomSpriteByIndex(tierIndex);
|
|
snapshot.sliderColor = GetSliderColorByIndex(tierIndex);
|
|
|
|
if (displayIndex >= levels.Count - 1 && currentExp >= currentLevel.requiredEXP)
|
|
{
|
|
snapshot.sliderValue = 1f;
|
|
snapshot.xpText = "MAX";
|
|
return snapshot;
|
|
}
|
|
|
|
int floorExp = currentLevelIndex >= 0 ? currentLevel.requiredEXP : 0;
|
|
int nextLevelIndex = Mathf.Clamp(displayIndex + 1, 0, levels.Count - 1);
|
|
int nextExp = levels[nextLevelIndex].requiredEXP;
|
|
int range = Mathf.Max(1, nextExp - floorExp);
|
|
int gained = Mathf.Clamp(currentExp - floorExp, 0, range);
|
|
|
|
snapshot.sliderValue = Mathf.Clamp01(gained / (float)range);
|
|
|
|
int neededExp = nextExp - currentExp;
|
|
if (neededExp > 0)
|
|
{
|
|
snapshot.xpText = "NEED " + neededExp + " EXP";
|
|
}
|
|
else if (displayIndex >= levels.Count - 1)
|
|
{
|
|
snapshot.xpText = "MAX";
|
|
}
|
|
|
|
return snapshot;
|
|
}
|
|
|
|
private int ResolveTierIndex(AllyHero_SO.AllyLevelInfo levelInfo, int levelIndex, int levelCount)
|
|
{
|
|
if (levelInfo != null && !string.IsNullOrWhiteSpace(levelInfo.levelName))
|
|
{
|
|
string normalized = levelInfo.levelName.Trim().ToUpperInvariant();
|
|
if (normalized.Contains("S")) return 3;
|
|
if (normalized.Contains("A")) return 2;
|
|
if (normalized.Contains("B")) return 1;
|
|
if (normalized.Contains("C")) return 0;
|
|
}
|
|
|
|
if (levelCount <= 1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float normalizedIndex = levelIndex / (float)Mathf.Max(1, levelCount - 1);
|
|
if (normalizedIndex >= 0.99f) return 3;
|
|
if (normalizedIndex >= 0.66f) return 2;
|
|
if (normalizedIndex >= 0.33f) return 1;
|
|
return 0;
|
|
}
|
|
|
|
private Sprite GetLevelIconByIndex(int index)
|
|
{
|
|
if (idolLevelIcons == null || idolLevelIcons.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return idolLevelIcons[Mathf.Clamp(index, 0, idolLevelIcons.Length - 1)];
|
|
}
|
|
|
|
private Sprite GetBottomSpriteByIndex(int index)
|
|
{
|
|
if (idolBtm == null || idolBtm.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return idolBtm[Mathf.Clamp(index, 0, idolBtm.Length - 1)];
|
|
}
|
|
|
|
private Color GetSliderColorByIndex(int index)
|
|
{
|
|
if (idolSliderColors == null || idolSliderColors.Length == 0)
|
|
{
|
|
return Color.white;
|
|
}
|
|
|
|
return idolSliderColors[Mathf.Clamp(index, 0, idolSliderColors.Length - 1)];
|
|
}
|
|
|
|
private void ClearCards()
|
|
{
|
|
for (int i = spawnedCards.Count - 1; i >= 0; i--)
|
|
{
|
|
if (spawnedCards[i] == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
DestroyImmediate(spawnedCards[i]);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Destroy(spawnedCards[i]);
|
|
}
|
|
}
|
|
|
|
spawnedCards.Clear();
|
|
|
|
if (idolCardParent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = idolCardParent.childCount - 1; i >= 0; i--)
|
|
{
|
|
Transform child = idolCardParent.GetChild(i);
|
|
if (child == null || child.GetComponent<idolCardPrefab>() == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
DestroyImmediate(child.gameObject);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Destroy(child.gameObject);
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct IdolLevelSnapshot
|
|
{
|
|
public float sliderValue;
|
|
public string xpText;
|
|
public Sprite levelIcon;
|
|
public Sprite bottomSprite;
|
|
public Color sliderColor;
|
|
}
|
|
}
|