using RPGCore.Core.Objects;
using RPGCore.ObjectModules.EventObjectModule;
using RPGCore.Stats.ObjectModules.StatsObjectModule.Events;
using RPGCoreCommon.DynamicValues;
using UnityEngine;
namespace RPGCore.Stats.ObjectModules.StatsObjectModule
{
///
/// You should never instantiate this by yourself!
/// Instantiated automatically by for every available .
///
public sealed class StatValue
{
public readonly StatDefinitionSO definition;
private readonly BaseObject _parent;
public readonly DynamicValueSourceContext sourceContext = new();
///
/// Base value defined in attached to .
/// Formula result will be added to this base value.
/// Default base value is ZERO.
///
public int baseValue { get; private set; }
///
/// This value is calculated by in and can have two meanings:
/// 1. If - just simple value stat
/// 2. If - this is maximum value for that resource
///
public int value { get; private set; }
///
/// Usable only when . is .
/// This value represent current resource of this stat. Always between and
///
public int resource { get; private set; }
internal StatValue(StatDefinitionSO definition, int baseValue, BaseObject parent)
{
this.definition = definition;
_parent = parent;
this.baseValue = baseValue;
}
///
/// Refreshes , by calculating formula again.
///
internal void Refresh()
{
var previous = value;
value = baseValue + definition.dynamicValue.GetValue(sourceContext);
_parent.events.Invoke(new StatValueChangeEvent
{
after = value,
before = previous,
statDefinition = definition,
target = _parent
});
}
///
/// Sets new and then do to recalculate whole
///
/// New base value
public void SetBase(int amount)
{
baseValue = amount;
Refresh();
}
///
/// Changes (or simpler - uses) of this stat value by given amount.
/// It just calls with: +
///
/// Amount that will be added or subtracted from
public void ChangeResource(int amount)
{
SetResource(resource + amount);
}
///
/// Sets to given amount. Amount will be clamped between ZERO and .
///
/// New amount
public void SetResource(int amount)
{
var old = resource;
resource = Mathf.Clamp(amount, 0, value);
_parent.events.Invoke(new StatResourceChangeEvent
{
delta = resource - old,
after = resource,
before = old,
statDefinition = definition,
target = _parent
});
}
///
/// Sets to given percentage. Percentage will be clamped between ZERO and ONE.
///
/// New percentage
public void SetResource(float percentage)
{
SetResource(Mathf.CeilToInt(Mathf.Clamp01(percentage) * value));
}
}
}