You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1019 lines
38 KiB
C#
1019 lines
38 KiB
C#
using MalbersAnimations.Events;
|
|
using MalbersAnimations.Scriptables;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace MalbersAnimations
|
|
{
|
|
/// <summary> Component managing Stat Logic</summary>
|
|
[AddComponentMenu("Malbers/Stats/Stats Manager")]
|
|
public class Stats : MonoBehaviour, IAnimatorListener
|
|
{
|
|
//[Tooltip("Track these Stats in a Runtime Set")]
|
|
//[CreateScriptableAsset] public RuntimeStats Set;
|
|
|
|
/// <summary>List of Stats</summary>
|
|
public List<Stat> stats = new List<Stat>();
|
|
/// <summary>List of Stats Converted to Dictionary</summary>
|
|
public Dictionary<int, Stat> stats_D;
|
|
|
|
/// <summary>Stored Stat to use the 'Pin' Methods</summary>
|
|
public Stat PinnedStat;
|
|
|
|
public virtual bool OnAnimatorBehaviourMessage(string message, object value) => this.InvokeWithParams(message, value);
|
|
|
|
public void Initialize()
|
|
{
|
|
StopAllCoroutines();
|
|
|
|
stats_D = new Dictionary<int, Stat>();
|
|
|
|
foreach (var stat in stats)
|
|
{
|
|
if (stat.ID == null)
|
|
{
|
|
Debug.LogError("One of the Stats has an Empty ID", gameObject);
|
|
break;
|
|
}
|
|
stat.InitializeStat(this);
|
|
|
|
if (!stats_D.ContainsKey(stat.ID)) //Added by SkillManiacs 2020/10
|
|
{
|
|
stats_D.Add(stat.ID, stat); //Convert them to Dictionary
|
|
}
|
|
else
|
|
{
|
|
stats_D[stat.ID] = stat; //Replace it
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
|
|
private void OnEnable()
|
|
{
|
|
foreach (var stat in stats_D)
|
|
{
|
|
if (stat.Value.ID == null)
|
|
{
|
|
Debug.LogError("One of the Stats has an Empty ID", gameObject);
|
|
break;
|
|
}
|
|
stat.Value.InitializeStat(this);
|
|
}
|
|
}
|
|
|
|
private void OnDisable() => StopAllCoroutines();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Updates all Stats</summary>
|
|
public virtual void Stats_Update()
|
|
{
|
|
foreach (var s in stats) s.UpdateStat();
|
|
}
|
|
|
|
/// <summary>Updates a stat logic by its Stat ID</summary>
|
|
public virtual void Stats_Update(StatID iD) => Stats_Update(iD.ID);
|
|
|
|
public virtual void Stats_Update(int iD) => Stat_Get(iD)?.UpdateStat();
|
|
|
|
/// <summary> Reset a Stat to the Default Max Value</summary>
|
|
public virtual void Stat_Reset_to_Max(StatID iD) => Stat_Get(iD)?.Reset_to_Max();
|
|
|
|
/// <summary> Reset a Stat to the Default Min Value</summary>
|
|
public virtual void Stat_Reset_to_Min(StatID iD) => Stat_Get(iD)?.Reset_to_Min();
|
|
|
|
/// <summary>Disable a stat</summary>
|
|
public virtual void Stat_Disable(StatID iD) => Stat_Get(iD)?.SetActive(false);
|
|
|
|
/// <summary>Disable a stat Degeneration logic</summary>
|
|
public virtual void Stat_Degenerate_Off(StatID ID) => Stat_Get(ID)?.SetDegeneration(false);
|
|
|
|
/// <summary>Enable a stat Degeneration logic</summary>
|
|
public virtual void Stat_Degenerate_On(StatID ID) => Stat_Get(ID)?.SetDegeneration(true);
|
|
|
|
/// <summary>Disable a stat Regeneration logic</summary>
|
|
public virtual void Stat_Regenerate_Off(StatID ID) => Stat_Get(ID)?.SetRegeneration(false);
|
|
|
|
/// <summary>Enable a stat Regeneration logic</summary>
|
|
public virtual void Stat_Regenerate_On(StatID ID) => Stat_Get(ID)?.SetRegeneration(true);
|
|
|
|
|
|
#region Callbacks with StatID parameters
|
|
/// <summary>Enable a stat</summary>
|
|
public virtual void Stat_Enable(StatID iD) => Stat_Get(iD)?.SetActive(true);
|
|
|
|
/// <summary>Set PinnedStat searching for a StatID</summary>
|
|
public virtual void Stat_Pin(StatID ID) => Stat_Get(ID.ID);
|
|
|
|
/// <summary>Find a Stat Using a StatID and Return if the Stat is on the List. Also Saves it to the PinnedStat</summary>
|
|
public virtual Stat Stat_Get(StatID ID) => Stat_Get(ID.ID);
|
|
|
|
// <summary>Set the Inmune Value of a Stat to true</summary>
|
|
public virtual void Stat_Inmune_Activate(StatID ID) => Stat_Get(ID)?.SetInmune(true);
|
|
|
|
/// <summary>Set the Inmune Value of a Stat to false</summary>
|
|
public virtual void Stat_Inmune_Deactivate(StatID ID) => Stat_Get(ID)?.SetInmune(false);
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>Set PinnedStat searching for a Stat Name</summary>
|
|
public virtual void Stat_Pin(string name) => Stat_Get(name);
|
|
|
|
/// <summary>Set PinnedStat searching for a int ID value</summary>
|
|
public virtual void Stat_Pin(int ID) => Stat_Get(ID);
|
|
|
|
|
|
/// <summary>Find a Stat Using its name for the ID and Return if the Stat is on the List. Also Saves it to the PinnedStat</summary>
|
|
public virtual Stat Stat_Get(string name) => PinnedStat = stats.Find(item => item.Name == name);
|
|
|
|
/// <summary>Find a Stat Using a int Value for the ID and Return if the Stat is on the List. Also Saves it to the PinnedStat</summary>
|
|
public virtual Stat Stat_Get(int ID)
|
|
{
|
|
if (stats_D != null && stats_D.TryGetValue(ID, out PinnedStat))
|
|
return PinnedStat;
|
|
return null;
|
|
}
|
|
/// <summary>Find a Stat Using an IntVar and Return if the Stat is on the List. Also Saves it to the PinnedStat</summary>
|
|
public virtual Stat Stat_Get(IntVar ID) => Stat_Get(ID.Value);
|
|
|
|
public virtual void Stat_ModifyValue(StatID ID, float modifyvalue) => Stat_Get(ID)?.Modify(modifyvalue);
|
|
public virtual void Stat_ModifyValue(int ID, float modifyvalue) => Stat_Get(ID)?.Modify(modifyvalue);
|
|
public virtual void Stat_ModifyValue(string name, float modifyvalue) => Stat_Get(name)?.Modify(modifyvalue);
|
|
|
|
public virtual void Stat_ModifyValue(StatID ID, float modifyvalue, StatOption modifyType) => Stat_Get(ID)?.Modify(modifyvalue, modifyType);
|
|
public virtual void Stat_ModifyValue(string name, float modifyvalue, StatOption modifyType) => Stat_Get(name)?.Modify(modifyvalue, modifyType);
|
|
|
|
/// <summary>Modify Stat Value instantly (Add/Remove to the Value)</summary>
|
|
public virtual void Stat_Pin_ModifyValue(float value) => PinnedStat?.Modify(value);
|
|
|
|
/// <summary>Modify Stat Value instantly (Add/Remove to the Value)</summary>
|
|
public virtual void Stat_Pin_ModifyValue(FloatVar value) => PinnedStat?.Modify(value.Value);
|
|
|
|
/// <summary>Modify Stat Value instantly (Add/Remove to the Value)</summary>
|
|
public virtual void Stat_Pin_SetMult(float value) => PinnedStat?.SetMultiplier(value);
|
|
|
|
/// <summary>Modify Stat Value instantly (Add/Remove to the Value)</summary>
|
|
public virtual void Stat_Pin_SetMult(FloatVar value) => PinnedStat?.SetMultiplier(value.Value);
|
|
|
|
/// <summary>Modify Stat Value in a X time period(Add/Remove to the Value)</summary>
|
|
public virtual void Stat_Pin_ModifyValue(float value, float time) => PinnedStat?.Modify(value, time);
|
|
|
|
/// <summary>Modify Stat Value in 1 second period(Add/Remove to the Value)</summary>
|
|
public virtual void Stat_Pin_ModifyValue_1Sec(float value) => PinnedStat?.Modify(value, 1);
|
|
|
|
/// <summary>Set Stat Value to a fixed Value</summary>
|
|
public virtual void Stat_Pin_SetValue(float value) => PinnedStat.SetValue(value);
|
|
|
|
/// <summary>Modify the Pinned Stat MAX Value (Add or remove to the Max Value) </summary>
|
|
public virtual void Stat_Pin_ModifyMaxValue(float value) => PinnedStat?.ModifyMAX(value);
|
|
|
|
/// <summary>Set the Pinned Stat MAX Value </summary>
|
|
public virtual void Stat_Pin_SetMaxValue(float value) => PinnedStat?.SetMAX(value);
|
|
|
|
/// <summary> Enable/Disable the Pinned Stat Regeneration Rate </summary>
|
|
public virtual void Stat_Pin_Modify_RegenRate(float value) => PinnedStat?.ModifyRegenRate(value);
|
|
|
|
/// <summary> Enable/Disable the Pinned Stat Degeneration </summary>
|
|
public virtual void Stat_Pin_Degenerate(bool value) => PinnedStat?.SetDegeneration(value);
|
|
|
|
/// <summary> Enable/Disable the Pinned Stat Degeneration </summary>
|
|
public virtual void Stat_Pin_SetInmune(bool value) => PinnedStat?.SetInmune(value);
|
|
|
|
|
|
|
|
/// <summary>Enable/Disable the Pinned Stat Regeneration </summary>
|
|
public virtual void Stat_Pin_Regenerate(bool value) => PinnedStat?.SetRegeneration(value);
|
|
// public virtual void _PinStatRegenerate(bool value) { Stat_Pin_Regenerate(value); }
|
|
|
|
/// <summary> Enable/Disable the Pinned Stat</summary>
|
|
public virtual void Stat_Pin_Enable(bool value) => PinnedStat?.SetActive(value);
|
|
|
|
/// <summary>Modify the Pinned Stat value with a 'new Value', 'ticks' times , every 'timeBetweenTicks' seconds</summary>
|
|
public virtual void Stat_Pin_ModifyValue(float newValue, int ticks, float timeBetweenTicks) => PinnedStat?.Modify(newValue, ticks, timeBetweenTicks);
|
|
|
|
/// <summary> Clean the Pinned Stat from All Regeneration/Degeneration and Modify Tick Values </summary>
|
|
public virtual void Stat_Pin_CleanCoroutines() => PinnedStat?.CleanRoutines();
|
|
|
|
|
|
|
|
|
|
[Obsolete("Use Stat_Degenerate_Off instead")]
|
|
/// <summary>Disable a stat Degeneration logic</summary>
|
|
public virtual void DegenerateOff(StatID ID) => Stat_Degenerate_Off(ID);
|
|
|
|
[Obsolete("Use Stat_Degenerate_On instead")]
|
|
/// <summary>Enable a stat Degeneration logic</summary>
|
|
public virtual void DegenerateOn(StatID ID) => Stat_Degenerate_On(ID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
[ContextMenu("Create/Stamina")]
|
|
private void ConnectStamina()
|
|
{
|
|
if (stats == null) stats = new List<Stat>();
|
|
|
|
|
|
var staminaID = MTools.GetInstance<StatID>("Stamina");
|
|
|
|
|
|
if (staminaID != null)
|
|
{
|
|
var staminaStat = Stat_Get(staminaID);
|
|
|
|
if (staminaStat == null)
|
|
{
|
|
staminaStat = new Stat()
|
|
{
|
|
ID = staminaID,
|
|
value = new FloatReference(100),
|
|
InmuneTime = new FloatReference(0.5f),
|
|
regenerate = new BoolReference(true),
|
|
RegenRate = new FloatReference(40),
|
|
DegenRate = new FloatReference(20),
|
|
RegenWaitTime = new FloatReference(2),
|
|
Above = 15f, Below = 10f,
|
|
};
|
|
stats.Add(staminaStat);
|
|
}
|
|
|
|
//Connect to the Animal Controller in case it exist
|
|
var method = this.GetUnityAction<bool>("MAnimal", "UseSprint");
|
|
|
|
if (method != null)
|
|
{
|
|
Debug.Log("medho" + method.ToString());
|
|
UnityEditor.Events.UnityEventTools.AddBoolPersistentListener(staminaStat.OnStatBelow, method, false);
|
|
UnityEditor.Events.UnityEventTools.AddBoolPersistentListener(staminaStat.OnStatAbove, method, true);
|
|
}
|
|
|
|
MEvent UIStamina = MTools.GetInstance<MEvent>("UI Stamina Stat");
|
|
|
|
if (UIStamina)
|
|
{
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(staminaStat.OnValueChangeNormalized,UIStamina.Invoke);
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(staminaStat.OnStatFull,UIStamina.Invoke);
|
|
}
|
|
|
|
|
|
var onSprintEnable = this.GetFieldClass<BoolEvent>("MAnimal", "OnSprintEnabled");
|
|
|
|
if (onSprintEnable != null)
|
|
{
|
|
UnityEditor.Events.UnityEventTools.AddObjectPersistentListener<StatID>(onSprintEnable, Stat_Pin, staminaID);
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(onSprintEnable, Stat_Pin_Degenerate);
|
|
}
|
|
|
|
MTools.SetDirty(this);
|
|
}
|
|
}
|
|
|
|
[ContextMenu("Create/Health")]
|
|
void CreateHealth()
|
|
{
|
|
var health = MTools.GetInstance<StatID>("Health");
|
|
|
|
if (health != null)
|
|
{
|
|
|
|
var HealthStat = new Stat()
|
|
{
|
|
ID = health,
|
|
value = new FloatReference(100),
|
|
DisableOnEmpty = new BoolReference(true),
|
|
InmuneTime = new FloatReference(0.1f)
|
|
};
|
|
stats.Add(HealthStat);
|
|
|
|
|
|
var deathID = MTools.GetInstance<StateID>("Death");
|
|
|
|
var method = this.GetUnityAction<StateID>("MAnimal", "State_Activate");
|
|
|
|
if (method != null) UnityEditor.Events.UnityEventTools.AddObjectPersistentListener<StateID>(HealthStat.OnStatEmpty, method, deathID);
|
|
|
|
|
|
MEvent UIHealth = MTools.GetInstance<MEvent>("UI Health Stat");
|
|
|
|
if (UIHealth)
|
|
{
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(HealthStat.OnValueChangeNormalized, UIHealth.Invoke);
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(HealthStat.OnStatFull, UIHealth.Invoke);
|
|
}
|
|
|
|
MTools.SetDirty(this);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
[ContextMenu("Create/Mana")]
|
|
void CreateMana()
|
|
{
|
|
var Mana = MTools.GetInstance<StatID>("Mana");
|
|
|
|
if (Mana != null)
|
|
{
|
|
|
|
var HealthStat = new Stat()
|
|
{
|
|
ID = Mana,
|
|
value = new FloatReference(100),
|
|
DisableOnEmpty = new BoolReference(true),
|
|
InmuneTime = new FloatReference(0),
|
|
regenerate = new BoolReference(true),
|
|
RegenWaitTime = new FloatReference(2),
|
|
RegenRate = new FloatReference(10),
|
|
DegenRate = new FloatReference(10)
|
|
};
|
|
stats.Add(HealthStat);
|
|
|
|
|
|
MEvent UIHealth = MTools.GetInstance<MEvent>("UI Mana Stat");
|
|
|
|
if (UIHealth)
|
|
{
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(HealthStat.OnValueChangeNormalized, UIHealth.Invoke);
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(HealthStat.OnStatFull, UIHealth.Invoke);
|
|
}
|
|
|
|
MTools.SetDirty(this);
|
|
}
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
if (stats == null) stats = new List<Stat>();
|
|
|
|
CreateHealth();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
///──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
///──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
///STAT CLASS
|
|
///──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
///──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
|
|
[Serializable]
|
|
public class Stat
|
|
{
|
|
#region Variables
|
|
|
|
[Tooltip("Enable/Disable the Stat. Disable Stats cannot be modified")]
|
|
public bool active = true;
|
|
[Tooltip("Key Idendifier for the Stat")]
|
|
public StatID ID;
|
|
[Tooltip("Current Value of the Stat")]
|
|
public FloatReference value = new FloatReference(0);
|
|
[Tooltip("Maximun Value of the Stat")]
|
|
public FloatReference maxValue = new FloatReference(100);
|
|
[Tooltip("Minimum Value of the Stat")]
|
|
public FloatReference minValue = new FloatReference();
|
|
[Tooltip("If the Stat is Empty it will be disabled to avoid future changes")]
|
|
public BoolReference DisableOnEmpty = new BoolReference();
|
|
|
|
/// <summary>Multiplier to modify the Stat value</summary>
|
|
[SerializeField] internal FloatReference multiplier = new FloatReference(1);
|
|
|
|
/// <summary>Can the Stat regenerate overtime</summary>
|
|
[SerializeField] internal BoolReference regenerate = new BoolReference( false);
|
|
/// <summary>Regeneration Rate. Change the Speed of the Regeneration</summary>
|
|
public FloatReference RegenRate;
|
|
/// <summary>Regeneration Rate. When the value is modified this will increase or decrease it over time.</summary>
|
|
public FloatReference RegenWaitTime = new FloatReference(0);
|
|
/// <summary>Regeneration Rate. When the value is modified this will increase or decrease it over time.</summary>
|
|
public FloatReference DegenWaitTime = new FloatReference(0);
|
|
/// <summary>Can the Stat degenerate overtime</summary>
|
|
[SerializeField] internal BoolReference degenerate = new BoolReference(false);
|
|
/// <summary>Degeneration Rate. Change the Speed of the Degeneration</summary>
|
|
public FloatReference DegenRate;
|
|
/// <summary>If greater than zero, the Stat cannot be modify until the inmune time have passed</summary>
|
|
public FloatReference InmuneTime;
|
|
/// <summary>If the ResetStat funtion is called it will reset to Max or Low Value</summary>
|
|
public ResetTo resetTo = ResetTo.MaxValue;
|
|
/// <summary> Save the Last State of the Regeneration bool</summary>
|
|
private bool regenerate_LastValue;
|
|
/// <summary> Save the Last State of the Regeneration bool</summary>
|
|
private bool degenerate_LastValue;
|
|
/// <summary> Is the Stat Below the Below Value</summary>
|
|
private bool isBelow = false;
|
|
/// <summary> Is the Stat Above the Above Value</summary>
|
|
private bool isAbove = false;
|
|
#endregion
|
|
|
|
#region Events
|
|
public UnityEvent OnStatFull = new UnityEvent();
|
|
public UnityEvent OnStatEmpty = new UnityEvent();
|
|
public UnityEvent OnStat = new UnityEvent();
|
|
public float Below;
|
|
public float Above;
|
|
public UnityEvent OnStatBelow = new UnityEvent();
|
|
public UnityEvent OnStatAbove = new UnityEvent();
|
|
public FloatEvent OnValueChangeNormalized = new FloatEvent();
|
|
public FloatEvent OnValueChange = new FloatEvent();
|
|
public BoolEvent OnDegenerate = new BoolEvent();
|
|
public BoolEvent OnRegenerate = new BoolEvent();
|
|
public BoolEvent OnActive = new BoolEvent();
|
|
#endregion
|
|
|
|
#region Properties
|
|
/// <summary>Is the Stat Enabled? when Disable no modification can be done. All current modification can't be stopped</summary>
|
|
public bool Active
|
|
{
|
|
get => active;
|
|
set
|
|
{
|
|
active = value;
|
|
|
|
OnActive.Invoke(value);
|
|
if (value)
|
|
StartRegeneration(); //If the Stat was activated start the regeneration
|
|
else
|
|
StopRegeneration();
|
|
}
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
if (ID != null)
|
|
{
|
|
return ID.name;
|
|
}
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
/// <summary> Current value of the Stat</summary>
|
|
public float Value
|
|
{
|
|
get => value;
|
|
set => SetValue(value);
|
|
}
|
|
|
|
public bool IsFull => Value == MaxValue;
|
|
public bool IsEmpty => Value == MinValue;
|
|
|
|
/// <summary> Current Multiplier of the Stat</summary>
|
|
public float Multiplier { get => multiplier.Value; set => multiplier.Value = value; }
|
|
|
|
/// <summary>Returns the Normalized value of the Stat</summary>
|
|
public float NormalizedValue => Value / MaxValue;
|
|
|
|
/// <summary>If True: The Stat cannot be modify </summary>
|
|
public bool IsInmune { get; set; }
|
|
|
|
/// <summary>Maximum Value of the Stat</summary>
|
|
public float MaxValue { get => maxValue.Value; set => maxValue.Value = value; }
|
|
|
|
/// <summary>Minimun Value of the Stat </summary>
|
|
public float MinValue { get => minValue.Value; set => minValue.Value = value; }
|
|
|
|
/// <summary>Is the Stat Regenerating?</summary>
|
|
public bool IsRegenerating { get; private set; }
|
|
|
|
/// <summary>Is the Stat Degenerating?</summary>
|
|
public bool IsDegenerating { get; private set; }
|
|
|
|
[SerializeField] internal int EditorTabs = 0;
|
|
|
|
/// <summary>Can the Stat Regenerate over time</summary>
|
|
public bool Regenerate
|
|
{
|
|
get => regenerate.Value;
|
|
set
|
|
{
|
|
regenerate.Value = value;
|
|
regenerate_LastValue = regenerate; //In case Regenerate is changed
|
|
OnRegenerate.Invoke(value);
|
|
|
|
if (regenerate)
|
|
{
|
|
degenerate.Value = false; //Do not Degenerate if we are Regenerating
|
|
StopDegeneration();
|
|
StartRegeneration();
|
|
}
|
|
else
|
|
{
|
|
degenerate.Value = degenerate_LastValue; //If we are no longer Regenerating Start Degenerating again in case the Degenerate was true
|
|
StopRegeneration();
|
|
StartDegeneration();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary> Can the Stat Degenerate over time </summary>
|
|
public bool Degenerate
|
|
{
|
|
get => degenerate.Value;
|
|
set
|
|
{
|
|
degenerate.Value = value;
|
|
degenerate_LastValue = degenerate; //In case Regenerate is changed
|
|
OnDegenerate.Invoke(value);
|
|
|
|
if (degenerate)
|
|
{
|
|
regenerate.Value = false; //Do not Regenerate if we are Degenerating
|
|
StartDegeneration();
|
|
StopRegeneration();
|
|
}
|
|
else
|
|
{
|
|
regenerate.Value = regenerate_LastValue; //If we are no longer Degenerating Start Regenerating again in case the Regenerate was true
|
|
StopDegeneration();
|
|
StartRegeneration();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
[NonSerialized] private WaitForSeconds InmuneWait;
|
|
|
|
internal void InitializeStat(Stats holder)
|
|
{
|
|
isAbove = isBelow = false;
|
|
Owner = holder; //Save the Monobehaviour to save coroutines
|
|
|
|
if (value.Value >= Above) isAbove = true; //This means that The Stat Value is over the Above value
|
|
else if (value.Value <= Below) isBelow = true; //This means that The Stat Value is under the Below value
|
|
|
|
regenerate_LastValue = Regenerate;
|
|
|
|
if (MaxValue < Value) MaxValue = Value;
|
|
|
|
|
|
I_Regeneration = null;
|
|
I_Degeneration = null;
|
|
I_ModifyPerTicks = null;
|
|
|
|
InmuneWait = new WaitForSeconds(InmuneTime);
|
|
|
|
if (Active)
|
|
{
|
|
StartRegeneration();
|
|
StartDegeneration();
|
|
}
|
|
|
|
holder.Delay_Action(3,() => ValueEvents());
|
|
}
|
|
|
|
internal void SetMultiplier(float value) => multiplier.Value = value;
|
|
|
|
|
|
internal void ValueEvents()
|
|
{
|
|
OnValueChangeNormalized.Invoke(NormalizedValue);
|
|
OnValueChange.Invoke(value);
|
|
|
|
|
|
if (this.value == minValue.Value)
|
|
{
|
|
this.value.Value = minValue.Value;
|
|
OnStatEmpty.Invoke(); //if the Value is 0 invoke Empty Stat
|
|
|
|
if (DisableOnEmpty.Value)
|
|
{
|
|
SetActive(false);
|
|
return;
|
|
}
|
|
|
|
}
|
|
else if (this.value == maxValue.Value)
|
|
{
|
|
this.value.Value = maxValue.Value;
|
|
OnStatFull.Invoke(); //if the Value is 0 invoke Empty Stat
|
|
}
|
|
|
|
|
|
if (this.value >= Above && !isAbove)
|
|
{
|
|
OnStatAbove.Invoke();
|
|
isAbove = true;
|
|
isBelow = false;
|
|
}
|
|
else if (this.value <= Below && !isBelow)
|
|
{
|
|
OnStatBelow.Invoke();
|
|
isBelow = true;
|
|
isAbove = false;
|
|
}
|
|
}
|
|
|
|
internal void SetValue(float value)
|
|
{
|
|
var RealValue = Mathf.Clamp(value * Multiplier, MinValue, maxValue);
|
|
|
|
if ((!Active) || //If the Stat is not Active do nothing
|
|
(this.value.Value == RealValue)) return; //If the values are equal do nothing. Avoid Stack Overflow
|
|
|
|
this.value.Value = RealValue;
|
|
|
|
ValueEvents();
|
|
}
|
|
|
|
/// <summary>Enable or Disable a Stat </summary>
|
|
public void SetActive(bool value) => Active = value;
|
|
public void SetRegeneration(bool value) => Regenerate = value;
|
|
public void SetDegeneration(bool value) => Degenerate = value;
|
|
public void SetInmune(bool value) => IsInmune = value;
|
|
|
|
/// <summary>Adds or remove to the Stat Value </summary>
|
|
public virtual void Modify(float newValue)
|
|
{
|
|
if (!IsInmune && Active)
|
|
{
|
|
Value += newValue;
|
|
StartRegeneration();
|
|
if (!Regenerate)
|
|
StartDegeneration();
|
|
|
|
SetInmune();
|
|
}
|
|
}
|
|
|
|
public virtual void UpdateStat()
|
|
{
|
|
SetValue(value);
|
|
StartRegeneration();
|
|
if (!Regenerate)
|
|
StartDegeneration();
|
|
}
|
|
|
|
/// <summary>Adds or remove to the Stat Value</summary>
|
|
public virtual void Modify(float newValue, float time)
|
|
{
|
|
if (!IsInmune && Active)
|
|
{
|
|
StopSlowModification();
|
|
Owner.StartCoroutine(out I_ModifySlow, C_SmoothChangeValue(newValue, time));
|
|
SetInmune();
|
|
}
|
|
}
|
|
|
|
/// <summary> Modify the Stat value with a 'new Value', 'ticks' times , every 'timeBetweenTicks' seconds </summary>
|
|
public virtual void Modify(float newValue, int ticks, float timeBetweenTicks)
|
|
{
|
|
if (!Active) return; //Ignore if the Stat is Disable
|
|
StopCoroutine(I_ModifyPerTicks);
|
|
|
|
Owner.StartCoroutine(out I_ModifyPerTicks, C_ModifyTicksValue(newValue, ticks, timeBetweenTicks));
|
|
}
|
|
|
|
/// <summary> Add or Remove Value the 'MaxValue' of the Stat </summary>
|
|
public virtual void ModifyMAX(float newValue)
|
|
{
|
|
if (!Active) return; //Ignore if the Stat is Disable
|
|
MaxValue += newValue;
|
|
StartRegeneration();
|
|
}
|
|
|
|
/// <summary>Sets the 'MaxValue' of the Stat </summary>
|
|
public virtual void SetMAX(float newValue)
|
|
{
|
|
if (!Active) return;
|
|
MaxValue = newValue;
|
|
StartRegeneration();
|
|
}
|
|
|
|
|
|
/// <summary>Add or Remove Rate to the Regeneration Rate</summary>
|
|
public virtual void ModifyRegenRate(float newValue)
|
|
{
|
|
if (!Active) return; //Ignore if the Stat is Disable
|
|
|
|
RegenRate.Value += newValue;
|
|
StartRegeneration();
|
|
}
|
|
|
|
public virtual void SetRegenerationWait(float newValue)
|
|
{
|
|
if (!Active) return; //Ignore if the Stat is Disable
|
|
|
|
RegenWaitTime.Value = newValue;
|
|
|
|
if (RegenWaitTime < 0) RegenWaitTime.Value = 0;
|
|
}
|
|
|
|
/// <summary>Set a new Regeneration Rate</summary>
|
|
public virtual void SetRegenerationRate(float newValue)
|
|
{
|
|
if (!Active) return; //Ignore if the Stat is Disable
|
|
RegenRate.Value = newValue;
|
|
}
|
|
|
|
/// <summary> Reset the Stat to the Default Max Value</summary>
|
|
public virtual void Reset() => Value = (resetTo == ResetTo.MaxValue) ? MaxValue : MinValue;
|
|
|
|
/// <summary> Reset the Stat to the Default Min or Max Value</summary>
|
|
public virtual void Reset_to_Max() => Value = MaxValue;
|
|
|
|
/// <summary> Reset the Stat to the Default Min Value</summary>
|
|
public virtual void Reset_to_Min() => Value = MinValue;
|
|
/// <summary>Clean all Coroutines</summary>
|
|
internal void CleanRoutines()
|
|
{
|
|
StopDegeneration();
|
|
StopRegeneration();
|
|
StopTickDamage();
|
|
StopSlowModification();
|
|
}
|
|
|
|
|
|
public virtual void RegenerateOverTime(float time)
|
|
{
|
|
if (time <= 0)
|
|
{
|
|
StartRegeneration();
|
|
}
|
|
else
|
|
{
|
|
Owner.StartCoroutine(C_RegenerateOverTime(time));
|
|
}
|
|
}
|
|
|
|
protected virtual void SetInmune()
|
|
{
|
|
if (InmuneTime > 0)
|
|
{
|
|
StopCoroutine(I_IsInmune);
|
|
Owner.StartCoroutine(out I_IsInmune, C_InmuneTime());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void StopCoroutine(IEnumerator Cor)
|
|
{
|
|
if (Cor != null) Owner.StopCoroutine(Cor);
|
|
}
|
|
|
|
protected virtual void StartRegeneration()
|
|
{
|
|
StopRegeneration();
|
|
|
|
if (RegenRate == 0 || !Regenerate) return; //Means if there's no Regeneration
|
|
|
|
Owner.StartCoroutine(out I_Regeneration, C_Regenerate());
|
|
}
|
|
|
|
|
|
protected virtual void StartDegeneration()
|
|
{
|
|
StopDegeneration();
|
|
if (DegenRate == 0 || !Degenerate) return; //Means there's no Degeneration
|
|
|
|
Owner.StartCoroutine(out I_Degeneration, C_Degenerate());
|
|
}
|
|
|
|
protected virtual void StopRegeneration()
|
|
{
|
|
StopCoroutine(I_Regeneration); //If there was a regenation active .... interrupt it
|
|
|
|
I_Regeneration = null;
|
|
IsRegenerating = false;
|
|
}
|
|
|
|
protected virtual void StopDegeneration()
|
|
{
|
|
StopCoroutine(I_Degeneration); //if it was ALREADY Degenerating.. stop
|
|
|
|
I_Degeneration = null;
|
|
IsDegenerating = false;
|
|
}
|
|
|
|
protected virtual void StopTickDamage()
|
|
{
|
|
StopCoroutine(I_ModifyPerTicks); //if it was ALREADY Degenerating.. stop...
|
|
I_ModifyPerTicks = null;
|
|
}
|
|
|
|
protected virtual void StopSlowModification()
|
|
{
|
|
StopCoroutine(I_ModifySlow); //If there was a regenation active .... interrupt it
|
|
I_ModifySlow = null;
|
|
}
|
|
|
|
/// <summary>Modify the Stats on an animal </summary>
|
|
public void Modify(float Value, StatOption modify)
|
|
{
|
|
switch (modify)
|
|
{
|
|
case StatOption.AddValue:
|
|
Modify(Value);
|
|
break;
|
|
case StatOption.SetValue:
|
|
this.Value = Value;
|
|
break;
|
|
case StatOption.SubstractValue:
|
|
Modify(-Value);
|
|
break;
|
|
case StatOption.ModifyMaxValue:
|
|
ModifyMAX(Value);
|
|
break;
|
|
case StatOption.SetMaxValue:
|
|
MaxValue = Value;
|
|
break;
|
|
case StatOption.Degenerate:
|
|
DegenRate = Value;
|
|
Degenerate = true;
|
|
break;
|
|
case StatOption.StopDegenerate:
|
|
DegenRate = Value;
|
|
Degenerate = false;
|
|
break;
|
|
case StatOption.Regenerate:
|
|
Regenerate = true;
|
|
RegenRate = Value;
|
|
break;
|
|
case StatOption.StopRegenerate:
|
|
Regenerate = false;
|
|
RegenRate = Value;
|
|
break;
|
|
case StatOption.Reset:
|
|
Reset();
|
|
break;
|
|
case StatOption.ReduceByPercent:
|
|
Modify(-(MaxValue * Value / 100));
|
|
break;
|
|
case StatOption.IncreaseByPercent:
|
|
Modify(MaxValue * Value / 100);
|
|
break;
|
|
case StatOption.Multiplier:
|
|
Multiplier = Value;
|
|
break;
|
|
case StatOption.ResetToMax:
|
|
Reset_to_Max();
|
|
break;
|
|
case StatOption.ResetToMin:
|
|
Reset_to_Min();
|
|
break;
|
|
case StatOption.None:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#region Coroutines
|
|
/// <summary>
|
|
/// I need this to use coroutines in this class because it does not inherit from Monobehaviour, Also to Identify where is this Stat coming from
|
|
/// </summary>
|
|
public Stats Owner { get; private set; }
|
|
private IEnumerator I_Regeneration;
|
|
private IEnumerator I_Degeneration;
|
|
private IEnumerator I_ModifyPerTicks;
|
|
private IEnumerator I_ModifySlow;
|
|
private IEnumerator I_IsInmune;
|
|
|
|
|
|
protected IEnumerator C_RegenerateOverTime(float time)
|
|
{
|
|
float ReachValue = RegenRate > 0 ? MaxValue : MinValue; //Set to the default or 0
|
|
bool Positive = RegenRate > 0; //Is the Regeneration Positive?
|
|
float currentTime = Time.time;
|
|
|
|
while (Value != ReachValue || currentTime > time )
|
|
{
|
|
Value += (RegenRate * Time.deltaTime);
|
|
|
|
if (Positive && Value > MaxValue)
|
|
{
|
|
Value = MaxValue;
|
|
}
|
|
else if (!Positive && Value < 0)
|
|
{
|
|
Value = MinValue;
|
|
}
|
|
currentTime += Time.deltaTime;
|
|
|
|
yield return null;
|
|
}
|
|
yield return null;
|
|
}
|
|
|
|
protected IEnumerator C_InmuneTime()
|
|
{
|
|
IsInmune = true;
|
|
yield return InmuneWait;
|
|
IsInmune = false;
|
|
}
|
|
|
|
protected IEnumerator C_Regenerate()
|
|
{
|
|
yield return null;
|
|
|
|
if (RegenWaitTime > 0)
|
|
yield return new WaitForSeconds(RegenWaitTime); //Wait a time to regenerate
|
|
|
|
IsRegenerating = true;
|
|
|
|
|
|
|
|
while (Regenerate && Value < MaxValue)
|
|
{
|
|
Value += (RegenRate * Time.deltaTime);
|
|
yield return null;
|
|
}
|
|
|
|
IsRegenerating = false;
|
|
yield return null;
|
|
}
|
|
|
|
protected IEnumerator C_Degenerate()
|
|
{
|
|
yield return null;
|
|
|
|
if (DegenWaitTime > 0)
|
|
yield return new WaitForSeconds(DegenWaitTime); //Wait a time to regenerate
|
|
|
|
IsDegenerating = true;
|
|
|
|
while (Degenerate && Value > MinValue)
|
|
{
|
|
Value -= (DegenRate * Time.deltaTime);
|
|
yield return null;
|
|
}
|
|
IsDegenerating = false;
|
|
yield return null;
|
|
}
|
|
|
|
protected IEnumerator C_ModifyTicksValue(float value, int Ticks, float time)
|
|
{
|
|
var WaitForTicks = new WaitForSeconds(time);
|
|
|
|
for (int i = 0; i < Ticks; i++)
|
|
{
|
|
Value += value;
|
|
if (Value <= MinValue)
|
|
{
|
|
Value = MinValue;
|
|
break;
|
|
}
|
|
yield return WaitForTicks;
|
|
}
|
|
|
|
yield return null;
|
|
|
|
StartRegeneration();
|
|
}
|
|
|
|
protected IEnumerator C_SmoothChangeValue(float newvalue, float time)
|
|
{
|
|
StopRegeneration();
|
|
float currentTime = 0;
|
|
float currentValue = Value;
|
|
newvalue = Value + newvalue;
|
|
|
|
yield return null;
|
|
while (currentTime <= time)
|
|
{
|
|
|
|
Value = Mathf.Lerp(currentValue, newvalue, currentTime / time);
|
|
currentTime += Time.deltaTime;
|
|
|
|
yield return null;
|
|
}
|
|
Value = newvalue;
|
|
|
|
yield return null;
|
|
StartRegeneration();
|
|
}
|
|
#endregion
|
|
|
|
public enum ResetTo
|
|
{
|
|
MinValue,
|
|
MaxValue
|
|
}
|
|
}
|
|
|
|
|
|
} |