public void UnregisterHandler(int i_AttributeId, tnStatChangedCallback i_Callback)
    {
        tnAttribute attribute = null;

        if (m_Attributes.TryGetValue(i_AttributeId, out attribute))
        {
            attribute.statChangedEvent -= i_Callback;
        }
        else
        {
            List <tnStatChangedCallback> cache = null;
            if (m_CallbacksCache.TryGetValue(i_AttributeId, out cache))
            {
                if (cache != null)
                {
                    cache.Remove(i_Callback);

                    if (cache.Count == 0)
                    {
                        m_CallbacksCache.Remove(i_AttributeId);
                    }
                }
                else
                {
                    m_CallbacksCache.Remove(i_AttributeId);
                }
            }
        }
    }
    public void RegisterHandler(int i_AttributeId, tnStatChangedCallback i_Callback)
    {
        tnAttribute attribute = null;

        if (m_Attributes.TryGetValue(i_AttributeId, out attribute))
        {
            attribute.statChangedEvent += i_Callback;
            i_Callback(attribute.baseValue, attribute.value);
        }
        else
        {
            List <tnStatChangedCallback> cache = null;
            if (m_CallbacksCache.TryGetValue(i_AttributeId, out cache))
            {
                if (cache == null)
                {
                    cache = new List <tnStatChangedCallback>();
                }

                cache.Add(i_Callback);
            }
            else
            {
                cache = new List <tnStatChangedCallback>();
                cache.Add(i_Callback);

                m_CallbacksCache.Add(i_AttributeId, cache);
            }
        }
    }
    public tnAttribute GetAttribute(int i_HashCode)
    {
        tnAttribute attribute = null;

        if (m_Attributes.TryGetValue(i_HashCode, out attribute))
        {
            return(attribute);
        }

        return(null); // Attribute not found.
    }
    public void RemoveModifier(tnAttributeModifier i_Modifier)
    {
        if (i_Modifier == null)
        {
            return;
        }

        int attributeId = i_Modifier.attributeId;

        tnAttribute attribute = GetAttribute(attributeId);

        if (attribute != null)
        {
            attribute.RemoveModifier(i_Modifier);
        }
        else
        {
            List <tnAttributeModifier> cache = null;
            if (m_ModifiersCache.TryGetValue(attributeId, out cache))
            {
                if (cache != null)
                {
                    cache.Remove(i_Modifier);

                    if (cache.Count == 0)
                    {
                        m_ModifiersCache.Remove(attributeId);
                    }
                }
                else
                {
                    m_CallbacksCache.Remove(attributeId);
                }
            }
        }
    }
    public void AddModifier(tnAttributeModifier i_Modifier)
    {
        if (i_Modifier == null)
        {
            return;
        }

        int attributeId = i_Modifier.attributeId;

        tnAttribute attribute = GetAttribute(attributeId);

        if (attribute != null)
        {
            attribute.AddModifier(i_Modifier);
        }
        else
        {
            List <tnAttributeModifier> cache = null;
            if (m_ModifiersCache.TryGetValue(attributeId, out cache))
            {
                if (cache == null)
                {
                    cache = new List <tnAttributeModifier>();
                }

                cache.Add(i_Modifier);
            }
            else
            {
                cache = new List <tnAttributeModifier>();
                cache.Add(i_Modifier);

                m_ModifiersCache.Add(attributeId, cache);
            }
        }
    }
    // INTERNALS

    private void Internal_CreateAttributes()
    {
        // Clear attributes.

        m_Attributes.Clear();

        if (m_StatsDatabase == null)
        {
            return;
        }

        // Create new attributes.

        for (int statIndex = 0; statIndex < m_StatsDatabase.statsCount; ++statIndex)
        {
            tnStatEntry stat = m_StatsDatabase.GetStat(statIndex);

            string id = stat.attributeId;
            if (id != "")
            {
                tnAttribute attribute = new tnAttribute(stat.baseValue);
                int         hashCode  = StringUtils.GetHashCode(id);
                m_Attributes.Add(hashCode, attribute);
            }
        }

        // Apply cache to new attributes.

        foreach (int attributeId in m_Attributes.Keys)
        {
            // Callbacks.

            {
                List <tnStatChangedCallback> cachedCallbacks = null;
                if (m_CallbacksCache.TryGetValue(attributeId, out cachedCallbacks))
                {
                    if (cachedCallbacks != null)
                    {
                        for (int index = 0; index < cachedCallbacks.Count; ++index)
                        {
                            tnStatChangedCallback callback = cachedCallbacks[index];
                            if (callback != null)
                            {
                                RegisterHandler(attributeId, callback);
                            }
                        }

                        cachedCallbacks.Clear();
                    }

                    m_CallbacksCache.Remove(attributeId);
                }
            }

            // Modifiers.

            {
                List <tnAttributeModifier> cachedModifiers = null;
                if (m_ModifiersCache.TryGetValue(attributeId, out cachedModifiers))
                {
                    if (cachedModifiers != null)
                    {
                        for (int index = 0; index < cachedModifiers.Count; ++index)
                        {
                            tnAttributeModifier modifier = cachedModifiers[index];
                            if (modifier != null)
                            {
                                AddModifier(modifier);
                            }
                        }

                        cachedModifiers.Clear();
                    }

                    m_ModifiersCache.Remove(attributeId);
                }
            }
        }
    }
    private void Internal_DestroyAttributes()
    {
        // Save cache.

        foreach (int attributeId in m_Attributes.Keys)
        {
            tnAttribute attribute = m_Attributes[attributeId];

            if (attribute == null)
            {
                continue;
            }

            // Callbacks.

            {
                if (attribute.statChangedEvent != null)
                {
                    Delegate[] callbacks = attribute.statChangedEvent.GetInvocationList();
                    if (callbacks != null)
                    {
                        if (callbacks.Length > 0)
                        {
                            List <tnStatChangedCallback> cache = new List <tnStatChangedCallback>();

                            for (int index = 0; index < callbacks.Length; ++index)
                            {
                                tnStatChangedCallback callback = (tnStatChangedCallback)callbacks[index];

                                if (callback == null)
                                {
                                    continue;
                                }

                                cache.Add(callback);
                            }

                            m_CallbacksCache.Add(attributeId, cache);
                        }
                    }
                }
            }

            // Modifiers.

            {
                if (attribute.modifiersCount > 0)
                {
                    List <tnAttributeModifier> cache = new List <tnAttributeModifier>();

                    for (int index = 0; index < attribute.modifiersCount; ++index)
                    {
                        tnAttributeModifier modifier = attribute.GetModifier(index);

                        if (modifier == null)
                        {
                            continue;
                        }

                        cache.Add(modifier);
                    }

                    m_ModifiersCache.Add(attributeId, cache);
                }
            }
        }

        // Clear attributes.

        m_Attributes.Clear();
    }