96 lines
2.6 KiB
C#
96 lines
2.6 KiB
C#
using Chickensoft.Collections;
|
|
using Godot;
|
|
using System;
|
|
using Zennysoft.Ma.Adapter;
|
|
|
|
namespace Zennysoft.Game.Ma;
|
|
|
|
public class ExperiencePointsComponent : IExperiencePointsComponent
|
|
{
|
|
public IAutoProp<int> CurrentExp => _currentExp;
|
|
|
|
public IAutoProp<int> ExpToNextLevel => _expToNextLevel;
|
|
|
|
public IAutoProp<double> ExpGainRate => _expGainRate;
|
|
|
|
public IAutoProp<int> Level => _level;
|
|
|
|
private readonly AutoProp<int> _currentExp;
|
|
|
|
private readonly AutoProp<int> _expToNextLevel;
|
|
|
|
private readonly AutoProp<double> _expGainRate;
|
|
|
|
private readonly AutoProp<int> _level;
|
|
|
|
public event Action PlayerLevelUp;
|
|
|
|
public event Action PlayerLevelDown;
|
|
|
|
public ExperiencePointsComponent()
|
|
{
|
|
var firstLevelExpRequirement = ExpToNextLevelCalculation(1);
|
|
_expToNextLevel = new AutoProp<int>(firstLevelExpRequirement);
|
|
_currentExp = new AutoProp<int>(0);
|
|
_expGainRate = new AutoProp<double>(1);
|
|
_level = new AutoProp<int>(1);
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
_currentExp.OnNext(0);
|
|
_expGainRate.OnNext(1);
|
|
_level.OnNext(1);
|
|
var firstLevelExpRequirement = ExpToNextLevelCalculation(1);
|
|
_expToNextLevel.OnNext(firstLevelExpRequirement);
|
|
}
|
|
|
|
public void Gain(int baseExpGain)
|
|
{
|
|
var modifiedExpGain = baseExpGain * _expGainRate.Value;
|
|
_currentExp.OnNext(Mathf.RoundToInt(modifiedExpGain + _currentExp.Value));
|
|
while (_currentExp.Value >= _expToNextLevel.Value)
|
|
LevelUp();
|
|
}
|
|
|
|
public void GainUnmodified(int flatRateExp)
|
|
{
|
|
var newCurrentExpTotal = flatRateExp + _currentExp.Value;
|
|
_currentExp.OnNext(newCurrentExpTotal);
|
|
while (_currentExp.Value >= _expToNextLevel.Value)
|
|
LevelUp();
|
|
}
|
|
|
|
public void ModifyExpGainRate(double newRate) => _expGainRate.OnNext(newRate);
|
|
|
|
public void LevelUp()
|
|
{
|
|
SfxDatabase.Instance.Play(SoundEffect.LevelUp);
|
|
_level.OnNext(_level.Value + 1);
|
|
var expToNextLevel = ExpToNextLevelCalculation(_level.Value);
|
|
_currentExp.OnNext(_currentExp.Value - _expToNextLevel.Value);
|
|
_expToNextLevel.OnNext(expToNextLevel);
|
|
PlayerLevelUp?.Invoke();
|
|
}
|
|
|
|
public void LevelDown()
|
|
{
|
|
SfxDatabase.Instance.Play(SoundEffect.DecreaseStat);
|
|
_currentExp.OnNext(0);
|
|
|
|
if (_level.Value == 1)
|
|
return;
|
|
|
|
var newLevel = Mathf.Max(_level.Value - 1, 1);
|
|
_level.OnNext(newLevel);
|
|
var expToNextLevel = ExpToNextLevelCalculation(newLevel);
|
|
_expToNextLevel.OnNext(expToNextLevel);
|
|
PlayerLevelDown.Invoke();
|
|
}
|
|
|
|
private int ExpToNextLevelCalculation(int nextLevel)
|
|
{
|
|
return (int)(6.5 * nextLevel + 4.5 * Math.Pow(nextLevel, 2) + Math.Pow(nextLevel, 3));
|
|
}
|
|
}
|