128 lines
4.4 KiB
C#
128 lines
4.4 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
using VOID.Generic.Objects.Unit;
|
|
using VOID.Generic.Objects.Unit.Events;
|
|
using VOID.UserInterface.Game.LevelUp;
|
|
using VOID.Generic.Util;
|
|
using VOID.ScriptableObjects;
|
|
using VOID.ScriptableObjects.Player;
|
|
|
|
namespace VOID.Generic.Player
|
|
{
|
|
/// <summary>
|
|
/// Manages Player's main <see cref="UnitObject"/> exp and level. Also manages sources which increases experience.
|
|
/// </summary>
|
|
[DefaultExecutionOrder(-1)]
|
|
public class PlayerLevelManager : MonoBehaviour
|
|
{
|
|
public static PlayerLevelManager current { get; private set; }
|
|
|
|
// Cache
|
|
private UnitObject _mainUnit;
|
|
private Dictionary<LevelUpOption, int> _selectedOptionsCounter = new();
|
|
private List<LevelUpOption> _optionsAvailable = new();
|
|
private List<LevelUpOption> _optionsForSelection = new();
|
|
private int _remainingLevelUps;
|
|
|
|
// Config
|
|
[SerializeField] private List<LevelUpOption> _options = new();
|
|
[SerializeField, MinValue(1f)] private int _optionsPerLevel = 3;
|
|
|
|
private void Awake()
|
|
{
|
|
current = this;
|
|
_optionsAvailable = _options.ToList();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
PlayerController.current.OnMainUnitChange += OnMainUnitChange;
|
|
}
|
|
|
|
private void OnMainUnitChange(UnitObject unitObject)
|
|
{
|
|
if (_mainUnit)
|
|
{
|
|
_mainUnit.unitEvents.onLevelGain.RemoveListener(OnLevelUp);
|
|
}
|
|
|
|
_mainUnit = unitObject;
|
|
_mainUnit.unitEvents.onLevelGain.AddListener(OnLevelUp);
|
|
}
|
|
|
|
private void OnLevelUp(LevelGainEvent levelGainEvent)
|
|
{
|
|
_remainingLevelUps += levelGainEvent.amount;
|
|
|
|
OpenLevelUpChoice();
|
|
}
|
|
|
|
public void OpenLevelUpChoice()
|
|
{
|
|
// No level ups to use - do nothing
|
|
if (_remainingLevelUps <= 0) return;
|
|
|
|
if (_optionsAvailable.Count <= 0)
|
|
{
|
|
Debug.LogWarning($"No more {nameof(LevelUpOption)} available");
|
|
return;
|
|
}
|
|
|
|
LevelUpUI.current.Open(GetOptionsForSelection(), OnLevelUpOptionSelect);
|
|
}
|
|
|
|
private List<LevelUpOption> GetOptionsForSelection()
|
|
{
|
|
// Get cached if available (when player closed previous choice without selecting)
|
|
if (_optionsForSelection.Count > 0) return _optionsForSelection;
|
|
|
|
var optionsAvailable = _optionsAvailable.ToList();
|
|
_optionsForSelection.Clear();
|
|
|
|
// Rebuild options for selection without repeatations
|
|
while (true)
|
|
{
|
|
// No more available options
|
|
if (optionsAvailable.Count <= 0) break;
|
|
|
|
// Amount of wanted options achieved
|
|
if (_optionsForSelection.Count >= _optionsPerLevel) break;
|
|
|
|
// Builds options to select by player
|
|
var randomOption = RandomUtil.RandomElementByWeight(optionsAvailable, option => option.weight);
|
|
_optionsForSelection.Add(randomOption);
|
|
optionsAvailable.Remove(randomOption);
|
|
}
|
|
|
|
return _optionsForSelection;
|
|
}
|
|
|
|
private void OnLevelUpOptionSelect(LevelUpOption option)
|
|
{
|
|
var status = ScriptableObject.CreateInstance<BasicStatus>();
|
|
status.displayName = option.displayName;
|
|
status.displayIcon = option.displayIcon;
|
|
status.description = option.displayDescription;
|
|
status.effects = option.effects.ToList();
|
|
status.hidden = true;
|
|
status.permanent = true;
|
|
|
|
_mainUnit.statusManager.AddStatus(status);
|
|
|
|
_selectedOptionsCounter.TryAdd(option, 0);
|
|
_selectedOptionsCounter[option]++;
|
|
|
|
// Remove options from pool when it reached its availability limit
|
|
if (_selectedOptionsCounter[option] >= option.limit) _optionsAvailable.Remove(option);
|
|
|
|
// Clear cache so it can be rebuild again
|
|
_optionsForSelection.Clear();
|
|
|
|
// Checking if we got more level ups to distribute
|
|
_remainingLevelUps--;
|
|
if (_remainingLevelUps > 0) OpenLevelUpChoice();
|
|
}
|
|
}
|
|
} |