Files
VOIDRPG/Assets/90 - Scripts/Generic/Objects/Unit/UnitObjectLevel.cs
T
2026-07-09 21:33:33 +02:00

92 lines
2.9 KiB
C#

using System;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Unit.Events;
namespace VOID.Generic.Objects.Unit
{
/// <summary>
/// Manages everything related to level and experience for <see cref="UnitObject"/>
/// </summary>
[Serializable]
public class UnitObjectLevel : ObjectComponent<UnitObject>
{
#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;
}
}
}