//
        // Stats
        //



        /// <summary>
        ///     Adds a new Stat to this Character. Also creates an internal record for the stat.
        ///     Will not add a particular stat more than once.
        /// </summary>
        public void AddStat(AbstractStat newStat)
        {
            // Check if this stat was already added
            StatData statData = this.SearchStat(newStat);

            // Add the stat
            if (statData == null)
            {
                statData = new StatData(newStat, this.appliedStats);
                this.appliedStats.Add(statData);

                // Apply all abilities that this new stat takes
                foreach (AbilityData ability in this.appliedAbilities)
                {
                    statData.ApplyOneAbility(ability);
                }

                this.RecalculateAllLinkedStatsPools();
                this.UpdateReadOnlyStatsList();
            }
            else
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogWarning("The stat " + newStat.Name + " was already added to " + this.Name);
                }
            }
        }
        /// <summary>
        ///     Tells the system that the given stat was used. This is needed for UseAssigned SP calculations.
        ///     Call this whenever that given stat was used in your game logic. Call as many times as needed.
        ///     Will return false if the given stat was not found in this Character.
        /// </summary>
        /// <returns><c>true</c>, if the given stat exists in this Character <c>false</c> otherwise.</returns>
        /// <param name="statDefinition">The definition file of the stat</param>
        public bool MarkStatAsUsed(AbstractStat statDefinition)
        {
            StatData foundStat = this.SearchStat(statDefinition);

            if (foundStat != null)
            {
                foundStat.MarkStatAsUsed();
                return(true);
            }

            return(false);
        }
        /// <summary>
        ///     Takes a certain amount of SP out of the Character's unallocated pool
        ///     and puts it into the pool of the given stat.
        /// </summary>
        /// <returns><c>true</c>, if the given stat exists in this Character <c>false</c> otherwise.</returns>
        /// <param name="spToAdd">The amount of SP to add to the given stat and remove from the unallocated pool</param>
        /// <param name="statDefinition">The definition file for the stat</param>
        public bool AddStatPointsFromUnallocatedPool(int spToAdd, AbstractStat statDefinition)
        {
            StatData foundStat = this.SearchStat(statDefinition);

            if (foundStat != null)
            {
                this.PrivAddSpFromUnallocPool(spToAdd, foundStat);
                return(true);
            }

            return(false);
        }
        /// <summary>
        ///     Search for a stat in this Character by a Stat data asset (BaseStat, SecondaryStat, SkillStat).
        ///     Will return null if no such stat is found
        /// </summary>
        public StatData SearchStat(AbstractStat statDefinition)
        {
            if (statDefinition == null)
            {
                Debug.LogWarning("RpgCharacterData.SearchStat(AbstractStat) was given a null AbstractStat!");
                return(null);
            }

            StatData foundStat = null;

            foreach (StatData s in this.appliedStats)
            {
                if (s.StatReference.Id.Equals(statDefinition.Id))
                {
                    foundStat = s;
                    break;
                }
            }

            return(foundStat);
        }
        /// <summary>
        ///     Search for any Stat by name (not filename).
        ///     Will search among BaseStats, SecondaryStats, and SkillStats.
        ///     Will return null if not found
        /// </summary>
        public AbstractStat SearchAnyStat(string byName)
        {
            AbstractStat foundObject = null;

            foreach (BaseStat entry in this.baseStats)
            {
                if (entry.Name.Equals(byName))
                {
                    foundObject = entry;
                    break;
                }
            }

            if (foundObject == null)
            {
                foreach (SecondaryStat entry in this.secondaryStats)
                {
                    if (entry.Name.Equals(byName))
                    {
                        foundObject = entry;
                        break;
                    }
                }

                if (foundObject == null)
                {
                    foreach (SkillStat entry in this.skillStats)
                    {
                        if (entry.Name.Equals(byName))
                        {
                            foundObject = entry;
                            break;
                        }
                    }
                }
            }


            return(foundObject);
        }
        /// <summary>
        ///     Deserialization Constructor
        /// </summary>
        public StatData(StatPacket statPacket, List <StatData> appliedStats)
        {
            Debug.Assert(statPacket != null, "New StatData being given a null StatPacket!");
            Debug.Assert(appliedStats != null, "New StatData being given null list of applied stats!");

            this.statId        = new SaveableGuid(statPacket.statId);
            this.statReference = RpgDataRegistry.Instance.SearchAnyStat(this.statId.GuidData);

            Debug.Assert(this.statReference != null, "Could not deserialize a stat because its definition cannot be found. ID: " + statPacket.statId);

            this.type                  = this.statReference.GetStatType();
            this.rawSpPool             = statPacket.rawSpPool;
            this.useFactor             = statPacket.useFactor;
            this.characterAppliedStats = appliedStats;

            // Initialize the SpDeriver
            switch (this.type)
            {
            case StatType.Base:
                this.linkedStatsDerivedPool = new BaseSpDeriver(this.statReference as BaseStat);
                break;

            case StatType.Secondary:
                this.linkedStatsDerivedPool = new SecondarySpDeriver(this.statReference as SecondaryStat);
                break;

            case StatType.Skill:
                this.linkedStatsDerivedPool = new SkillSpDeriver(this.statReference as SkillStat);
                break;

            default:
                Debug.LogError("Somebody added a new entry into the enum StatType");
                break;
            }


            // Initialize the AbilityAggregator
            this.abilityModifications = new AbilityAggregator(this.statId.GuidData);
        }
        /// <summary>
        ///     StatData Constructor needs the stat definition file and the RpgCharacter's list of stats
        /// </summary>
        public StatData(AbstractStat newStat, List <StatData> appliedStats)
        {
            Debug.Assert(newStat != null, "New StatData being given a null AbstractStat!");
            Debug.Assert(appliedStats != null, "New StatData being given null list of applied stats!");

            this.statReference         = newStat;
            this.characterAppliedStats = appliedStats;
            this.statId    = new SaveableGuid(newStat.Id);
            this.type      = newStat.GetStatType();
            this.rawSpPool = 0;
            this.useFactor = 1;


            // Initialize the SpDeriver
            switch (this.type)
            {
            case StatType.Base:
                this.linkedStatsDerivedPool = new BaseSpDeriver(newStat as BaseStat);
                break;

            case StatType.Secondary:
                this.linkedStatsDerivedPool = new SecondarySpDeriver(newStat as SecondaryStat);
                break;

            case StatType.Skill:
                this.linkedStatsDerivedPool = new SkillSpDeriver(newStat as SkillStat);
                break;

            default:
                Debug.LogError("Somebody added a new entry into the enum StatType");
                break;
            }


            // Initialize the AbilityAggregator
            this.abilityModifications = new AbilityAggregator(this.statId.GuidData);
        }