Files
bansonic_beta_main/Assets/playerInfoDisplay/uls/uLevel_skills.cs
T

416 lines
11 KiB
C#

using UnityEngine;
using UnityEngine.UI;
public class uLevel_skills : MonoBehaviour
{
public userLevel_skills_SO ulsSO;
public Player_SO pso;
[Header("objs")]
public GameObject uSkillBarPrefab;
public Transform uSkillBarParent;
[Header("current selected skill details")]
public Image btm_skillImage;
public Image skillIcon_Profile;
public Text skill_thisSkillName;
public Text skill_thisSkillSummary;
[Header("change")]
public Slider need_progress;
public Text need_text;
public Text need_howmuchCoins;
public Button yesChangeButton;
public Button noCancelButton;
private readonly System.Collections.Generic.List<lrPrefab> spawnedBars = new System.Collections.Generic.List<lrPrefab>();
private bool hasStarted = false;
private int pendingSkillIndex = -1;
private Color defaultNeedCoinsColor = Color.white;
private const int SkillSwitchCooldownMatches = 3;
private const int SkillSwitchMinimumCost = 200;
private void Start()
{
hasStarted = true;
CacheUiDefaults();
RegisterButtons();
PlayerSkillService.RegisterSkillAsset(ulsSO);
RefreshSkillBars();
}
private void OnEnable()
{
CacheUiDefaults();
RegisterButtons();
PlayerSkillService.RegisterSkillAsset(ulsSO);
if (hasStarted)
{
RefreshSkillBars();
}
}
private void OnDestroy()
{
UnregisterButtons();
}
public void SetPlayerSo(Player_SO playerSo)
{
pso = playerSo;
}
public void RefreshSkillBars()
{
EnsurePlayerSo();
if (uSkillBarParent == null || uSkillBarPrefab == null || ulsSO == null)
return;
NormalizeSelectionState();
ClearExistingBars();
spawnedBars.Clear();
for (int i = 0; i < ulsSO.skills.Count; i++)
{
var entry = ulsSO.skills[i];
if (entry == null)
continue;
GameObject instance = Instantiate(uSkillBarPrefab, uSkillBarParent);
instance.SetActive(true);
lrPrefab bar = instance.GetComponent<lrPrefab>();
if (bar == null)
continue;
bar.Bind(this, ulsSO, i, entry, IsSkillUnlocked(entry));
spawnedBars.Add(bar);
}
RefreshDetailPanel();
RefreshChangeUi();
}
public void ToggleSkill(int index)
{
if (ulsSO == null || index < 0 || index >= ulsSO.skills.Count)
return;
var entry = ulsSO.skills[index];
if (entry == null || !IsSkillUnlocked(entry))
return;
int currentEnabledIndex = GetEnabledSkillIndex();
if (index == currentEnabledIndex)
{
pendingSkillIndex = -1;
RefreshDetailPanel();
RefreshChangeUi();
RefreshStatusesOnly();
return;
}
pendingSkillIndex = pendingSkillIndex == index ? -1 : index;
RefreshDetailPanel();
RefreshChangeUi();
RefreshStatusesOnly();
}
public bool IsSkillPreselected(int index)
{
return pendingSkillIndex >= 0 && pendingSkillIndex == index;
}
public bool IsSkillUnlocked(userLevel_skills_SO.UserLevelSkillEntry entry)
{
EnsurePlayerSo();
if (entry == null)
return false;
int currentExp = pso != null ? Mathf.Max(0, pso.player_currentEXP) : 0;
return currentExp >= Mathf.Max(0, entry.thisLevelNeedExps);
}
private void RefreshStatusesOnly()
{
for (int i = 0; i < spawnedBars.Count; i++)
{
if (spawnedBars[i] == null)
continue;
spawnedBars[i].RefreshVisualState();
}
}
private void RefreshDetailPanel()
{
if (ulsSO == null || ulsSO.skills == null || ulsSO.skills.Count == 0)
{
SetDetailPanel(null);
return;
}
int detailIndex = pendingSkillIndex >= 0 ? pendingSkillIndex : GetEnabledSkillIndex();
if (detailIndex < 0 || detailIndex >= ulsSO.skills.Count)
{
SetDetailPanel(null);
return;
}
SetDetailPanel(ulsSO.skills[detailIndex]);
}
private void SetDetailPanel(userLevel_skills_SO.UserLevelSkillEntry entry)
{
if (btm_skillImage != null)
{
btm_skillImage.sprite = entry != null ? entry.skillIcon : null;
}
if (skillIcon_Profile != null)
{
skillIcon_Profile.sprite = entry != null ? entry.skillIcon : null;
}
if (skill_thisSkillName != null)
{
skill_thisSkillName.text = entry != null ? (entry.skillName ?? string.Empty) : string.Empty;
}
if (skill_thisSkillSummary != null)
{
skill_thisSkillSummary.text = entry != null ? (entry.skillDescription ?? string.Empty) : string.Empty;
}
}
private void RefreshChangeUi()
{
int cooldownRemaining = PlayerSkillService.GetSkillSwitchCooldownRemainingMatches();
int currentEnabledIndex = GetEnabledSkillIndex();
bool hasPendingSelection = pendingSkillIndex >= 0 && pendingSkillIndex != currentEnabledIndex;
if (need_text != null)
{
need_text.text = cooldownRemaining > 0
? $"还需要{cooldownRemaining}场比赛"
: "可以切换技能";
}
if (need_progress != null)
{
need_progress.minValue = 0f;
need_progress.maxValue = 1f;
need_progress.value = cooldownRemaining > 0
? Mathf.Clamp01((float)(SkillSwitchCooldownMatches - cooldownRemaining) / SkillSwitchCooldownMatches)
: 1f;
}
int switchCost = GetSkillSwitchCost();
bool hasEnoughCoins = HasEnoughCoinsForSwitch(switchCost);
if (need_howmuchCoins != null)
{
need_howmuchCoins.text = switchCost.ToString();
need_howmuchCoins.color = hasEnoughCoins ? defaultNeedCoinsColor : Color.red;
}
if (yesChangeButton != null)
{
yesChangeButton.interactable = hasPendingSelection && cooldownRemaining <= 0 && hasEnoughCoins;
}
if (noCancelButton != null)
{
noCancelButton.interactable = pendingSkillIndex >= 0;
}
}
private int GetSkillSwitchCost()
{
int currentCoins = Application.isPlaying
? PlayerEconomyLedger.EnsureInstance().GetCoins()
: (pso != null ? Mathf.Max(0, pso.Coins) : 0);
int percentCost = Mathf.CeilToInt(currentCoins * 0.01f);
return Mathf.Max(SkillSwitchMinimumCost, percentCost);
}
private bool HasEnoughCoinsForSwitch(int amount)
{
if (amount <= 0)
return true;
return Application.isPlaying
? PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(amount)
: (pso != null && pso.Coins >= amount);
}
private void HandleConfirmSwitchClicked()
{
int currentEnabledIndex = GetEnabledSkillIndex();
if (pendingSkillIndex < 0 || pendingSkillIndex == currentEnabledIndex || ulsSO == null)
{
return;
}
if (PlayerSkillService.GetSkillSwitchCooldownRemainingMatches() > 0)
{
RefreshChangeUi();
return;
}
int switchCost = GetSkillSwitchCost();
bool spent = Application.isPlaying
? PlayerEconomyLedger.EnsureInstance().TrySpendCoins(switchCost)
: (pso != null && pso.TrySpendCoins(switchCost));
if (!spent)
{
RefreshChangeUi();
return;
}
PlayerSkillService.ConfirmSkillSelection(ulsSO, pendingSkillIndex);
pendingSkillIndex = -1;
MarkSkillsDirty();
RefreshStatusesOnly();
RefreshDetailPanel();
RefreshChangeUi();
}
private void HandleCancelPreselectClicked()
{
pendingSkillIndex = -1;
RefreshStatusesOnly();
RefreshDetailPanel();
RefreshChangeUi();
}
private void ClearExistingBars()
{
for (int i = uSkillBarParent.childCount - 1; i >= 0; i--)
{
Transform child = uSkillBarParent.GetChild(i);
if (Application.isPlaying)
Destroy(child.gameObject);
else
DestroyImmediate(child.gameObject);
}
}
private void MarkSkillsDirty()
{
#if UNITY_EDITOR
if (!Application.isPlaying && ulsSO != null)
UnityEditor.EditorUtility.SetDirty(ulsSO);
#endif
}
private void EnsurePlayerSo()
{
if (pso == null)
pso = Resources.Load<Player_SO>("playerdata/playerData_uniqueData");
}
private void CacheUiDefaults()
{
if (need_howmuchCoins != null)
{
defaultNeedCoinsColor = need_howmuchCoins.color;
}
}
private void RegisterButtons()
{
if (yesChangeButton != null)
{
yesChangeButton.onClick.RemoveListener(HandleConfirmSwitchClicked);
yesChangeButton.onClick.AddListener(HandleConfirmSwitchClicked);
}
if (noCancelButton != null)
{
noCancelButton.onClick.RemoveListener(HandleCancelPreselectClicked);
noCancelButton.onClick.AddListener(HandleCancelPreselectClicked);
}
}
private void UnregisterButtons()
{
if (yesChangeButton != null)
{
yesChangeButton.onClick.RemoveListener(HandleConfirmSwitchClicked);
}
if (noCancelButton != null)
{
noCancelButton.onClick.RemoveListener(HandleCancelPreselectClicked);
}
}
private int GetEnabledSkillIndex()
{
if (ulsSO == null || ulsSO.skills == null)
return -1;
for (int i = 0; i < ulsSO.skills.Count; i++)
{
var entry = ulsSO.skills[i];
if (entry != null && entry.isEnabled)
return i;
}
return -1;
}
private void NormalizeSelectionState()
{
if (ulsSO == null || ulsSO.skills == null || ulsSO.skills.Count == 0)
return;
int selectedIndex = -1;
for (int i = 0; i < ulsSO.skills.Count; i++)
{
var entry = ulsSO.skills[i];
if (entry == null || !entry.isEnabled)
continue;
if (selectedIndex < 0)
{
selectedIndex = i;
}
else
{
entry.isEnabled = false;
}
}
if (selectedIndex < 0)
{
for (int i = 0; i < ulsSO.skills.Count; i++)
{
var entry = ulsSO.skills[i];
if (entry == null)
continue;
selectedIndex = i;
entry.isEnabled = true;
break;
}
}
for (int i = 0; i < ulsSO.skills.Count; i++)
{
var entry = ulsSO.skills[i];
if (entry == null)
continue;
entry.isEnabled = (i == selectedIndex);
}
MarkSkillsDirty();
PlayerSkillService.RegisterSkillAsset(ulsSO);
pendingSkillIndex = -1;
}
}