using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; namespace CleverCrow.Fluid.StatsSystem.StatsContainers { [CreateAssetMenu(fileName = "StatsContainer", menuName = "Fluid/Stats/Container")] public class StatsContainer : ScriptableObject, IStatsContainer { public virtual string Id => name.Replace("(Copy)", ""); private class StatRecordEvent : UnityEvent {} private Dictionary _events = new Dictionary(); [Tooltip("This collection will be combined with the default stats from settings")] public StatDefinitionCollection collection; public StatRecordCollection records = new StatRecordCollection(); public StatRecordCollection Records => records; public StatDefinitionOverrideCollection overrides = new StatDefinitionOverrideCollection(); public bool IsSetup { get; private set; } /// /// Run initialization on the stats system /// public void Setup () { if (IsSetup) return; List definitions; if (collection == null) { definitions = StatsSettings.Current.DefinitionsCompiled.GetDefaults(); } else { definitions = StatsSettings.Current.DefinitionsCompiled.Get(collection); } if (definitions == null) { Debug.Assert(!Application.isPlaying, "Collection is required to initialize a StatsData component. Aborting setup."); return; } foreach (var statDefinition in definitions) { var @override = overrides.Get(statDefinition); var val = @override == null ? null : @override.value; records.Set(new StatRecord(statDefinition, val)); } IsSetup = true; } /// /// Retrieve a record by ID /// /// /// public StatRecord GetRecord (string definitionId) { return records.Get(definitionId); } public StatRecord GetRecord (StatDefinition definition) { return records.Get(definition); } /// /// Check if a record exists by ID /// /// /// public bool HasRecord (string definitionId) { return records.Has(definitionId); } public bool HasRecord (StatDefinition definition) { return records.Has(definition); } /// /// Retrieve a float value by record with an optional index /// /// /// /// public float GetStat (StatRecord record, float index = 0) { if (record == null) return 0; return record.GetValue(index); } public float GetStat (StatDefinition definition, float index = 0) { return GetStat(GetRecord(definition), index); } public float GetStat (string definitionId, float index = 0) { return GetStat(GetRecord(definitionId), index); } /// /// Retrieve an int value by record with an optional index /// /// /// /// public int GetStatInt (StatRecord record, float index = 0) { if (record == null) return 0; return Mathf.RoundToInt(record.GetValue(index)); } public int GetStatInt (StatDefinition definition, float index = 0) { return GetStatInt(GetRecord(definition), index); } public int GetStatInt (string definitionId, float index = 0) { return GetStatInt(GetRecord(definitionId), index); } /// /// Set a modifier by ID and value /// /// /// /// /// public void SetModifier (OperatorType operation, StatRecord record, string modifierId, float value) { if (record == null) return; record.GetModifier(operation).Set(modifierId, value); TriggerEvent(record); } public void SetModifier (OperatorType operation, StatDefinition definition, string modifierId, float value) { SetModifier(operation, GetRecord(definition), modifierId, value); } public void SetModifier (OperatorType operation, string definitionId, string modifierId, float value) { SetModifier(operation, GetRecord(definitionId), modifierId, value); } /// /// Retrieve the value of a modifier /// /// /// /// /// public float GetModifier (OperatorType operation, StatRecord record, string modifierId) { if (record == null) return 0; var modifier = record.GetModifier(operation).Get(modifierId); if (modifier == null) return 0; return modifier.value; } public float GetModifier (OperatorType operation, StatDefinition definition, string modifierId) { return GetModifier(operation, GetRecord(definition), modifierId); } public float GetModifier (OperatorType operation, string definitionId, string modifierId) { return GetModifier(operation, GetRecord(definitionId), modifierId); } /// /// Remove a modifier by ID /// /// /// /// /// public bool RemoveModifier (OperatorType operation, StatRecord record, string modifierId) { if (record == null) return false; var result = record.GetModifier(operation).Remove(modifierId); TriggerEvent(record); return result; } public bool RemoveModifier (OperatorType operation, StatDefinition definition, string modifierId) { return RemoveModifier(operation, GetRecord(definition), modifierId); } public bool RemoveModifier (OperatorType operation, string definitionId, string modifierId) { return RemoveModifier(operation, GetRecord(definitionId), modifierId); } /// /// Wipe all modifiers (add, sub, mult, div) on a particular record /// /// /// public void ClearAllModifiers (StatRecord record, string modifierId) { RemoveModifier(OperatorType.Add, record, modifierId); RemoveModifier(OperatorType.Subtract, record, modifierId); RemoveModifier(OperatorType.Multiply, record, modifierId); RemoveModifier(OperatorType.Divide, record, modifierId); TriggerEvent(record); } /// /// Wipe all modifiers associated with the ID on every record /// /// public void ClearAllModifiers (string modifierId) { records.records.ForEach(r => ClearAllModifiers(r, modifierId)); } /// /// Alias for ClearAllModifiers, except it wipes an array of strings /// /// Modifier identifiers. public void ClearAllModifiers (List modifierIds) { if (modifierIds == null) return; modifierIds.ForEach(m => ClearAllModifiers(m)); } /// /// Does not copy over events. /// /// public StatsContainer CreateRuntimeCopy () { var copy = Instantiate(this); copy.Setup(); return copy; } private void TriggerEvent (StatRecord record) { if (record != null && _events.TryGetValue(record, out var @event)) { @event.Invoke(record); } } public void OnStatChangeSubscribe (StatRecord record, UnityAction callback) { if (!_events.TryGetValue(record, out var @event)) { @event = new StatRecordEvent(); _events[record] = @event; } @event.AddListener(callback); } public void OnStatChangeSubscribe (StatDefinition definition, UnityAction callback) { var record = GetRecord(definition); OnStatChangeSubscribe(record, callback); } public void OnStatChangeSubscribe (string definitionId, UnityAction callback) { var record = GetRecord(definitionId); OnStatChangeSubscribe(record, callback); } public void OnStatChangeUnsubscribe (StatRecord record, UnityAction callback) { _events[record].RemoveListener(callback); } public void OnStatChangeUnsubscribe (StatDefinition definition, UnityAction callback) { var record = GetRecord(definition); OnStatChangeUnsubscribe(record, callback); } public void OnStatChangeUnsubscribe (string definitionId, UnityAction callback) { var record = GetRecord(definitionId); OnStatChangeUnsubscribe(record, callback); } } }