using System; using Sirenix.OdinInspector; using UnityEngine; using VOID.Generic.Objects.Unit.Events; namespace VOID.Generic.Objects.Unit { /// /// Manages everything related to level and experience for /// [Serializable] public class UnitObjectLevel : ObjectComponent { #region Initialize protected override void SelfInitialize() { _expNeeded = GetExpNeededForLevel(_level + 1); } #endregion [Header("Constants:")] [ShowInInspector, ReadOnly] public const int ExpNeededForFirstLevel = 100; [ShowInInspector, ReadOnly] public const float ExpNeededMultiplierPerLevel = 1.25f; [Header("Current:")] [SerializeField, ReadOnly, MinValue(1)] private int _level = 1; [ShowInInspector, ReadOnly] private int _exp; [ShowInInspector, ReadOnly] private int _expNeeded; public int level => _level; public int exp => _exp; public int expNeeded => _expNeeded; [Button] public void SetLevel(int value) { _level = Mathf.Max(1, value); _exp = 0; _expNeeded = GetExpNeededForLevel(_level + 1); } [Button] [DisableInEditorMode] public void AddLevel(int amount) => Add(levelToAdd: amount); [Button] [DisableInEditorMode] public void AddExperience(int amount) => Add(expToAdd: amount); [Button] [DisableInEditorMode] public void Add(int levelToAdd = 0, int expToAdd = 0) { if (levelToAdd <= 0 && expToAdd <= 0) return; // Directly increasing level also resets current experience if (levelToAdd > 0) { _level += levelToAdd; _exp = 0; } _exp += expToAdd; // Convert EXP to LEVELS while (_exp >= _expNeeded) { levelToAdd++; _exp -= _expNeeded; _expNeeded = GetExpNeededForLevel(_level + 1 + levelToAdd); } if (expToAdd > 0) parent.unitEvents.onExpGain.Invoke(new ExpGainEvent { unit = parent, amount = expToAdd }); if (levelToAdd > 0) parent.unitEvents.onLevelGain.Invoke(new LevelGainEvent { unit = parent, amount = levelToAdd }); } private int GetExpNeededForLevel(int forLevel) { // Exp needed can be calculated only for level 2 and higher! if (forLevel < 2) return 0; var expMultiplierForLevel = Mathf.Pow(ExpNeededMultiplierPerLevel, forLevel - 2); var expNeededForLevel = Mathf.FloorToInt(ExpNeededForFirstLevel * expMultiplierForLevel); return expNeededForLevel; } } }