UNITY : Remove stat modifier from character stats when unequipping

Viewed 51

Sorry for the lenght of this in advance, its hard to explain without all the code.

I used Kryzarel code on implementing a character stats and stat modifier system. https://www.youtube.com/watch?v=SH25f3cXBVc

I customized how the equipment modifiers and character stats are stored and when equipping an item to my character. It works perfect when equipping it but upon unequipping it, it does not seem to remove the stat modifier from the list?

CharacterStats Class holding all the stats for my character

[AttributeUsage(AttributeTargets.Field)]
public class BaseStat : Attribute {}

[Serializable]
public class Stats 
{

    [BaseStat] public CharacterStat vitality;               
    [BaseStat] public CharacterStat stamina;                 
    [BaseStat] public CharacterStat endurance;  
}           

EquipmentStats Class holding all the stats for my equipment(I did not post all stats because I have 53 of them)

[Serializable]
public class StatMods 
{
    public float vitality;
    public float stamina;
    public float endurance;
    public StatModifier vitalityMod;               
    public StatModifier staminaMod;                 
    public StatModifier enduranceMod;
    public void UpdateModifiers()
    {
        vitalityMod = new StatModifier(vitality, StatModifierType.Flat);              
        staminaMod = new StatModifier(stamina, StatModifierType.Flat);                 
        enduranceMod = new StatModifier(endurance, StatModifierType.Flat);
    }
}

Character Class implementing the equip and unequip Methods

public class Character : MonoBehaviour
{
    /*-------------------------------------------------------------------------------------------------------------------------
                FIELDS                                                                                   
    -------------------------------------------------------------------------------------------------------------------------*/    
    public CharacterStats characterStats;
    [EnumNamedArray(typeof(EquipmentSlot))]
    public Equipment[] currentEquipment;
    private System.Random ran;
    public string weapon;
    public bool attackingFocus;
    public float attackCooldown = 0f;
    public InteractAble focusCurrent;
    public InteractAble focusNew;
    public bool aggro = false; 
    public Stats stats;
    /*-------------------------------------------------------------------------------------------------------------------------
                METHODS                                                                                   
    -------------------------------------------------------------------------------------------------------------------------*/
    /*-------------------------------------------------------------------------------------------
                METHODS - EQUIPMENT STATS                                                                                 
    -------------------------------------------------------------------------------------------*/        
    public void AddEquipmentStats(Equipment equippedItem)
    {
        // Getting Character Stats
        FieldInfo[] fis = Members.GetFields(stats);
        // Updating Modifiers -- assigning values that equipment hold to the modifiers
        equippedItem.statMods.UpdateModifiers();
        for (int i = 0; i < fis.Length; i++) 
        { 
            BaseStat attribute = Attribute.GetCustomAttribute(fis[i], typeof(BaseStat)) as BaseStat;
            if (attribute != null)
            {
                // Getting CharacterStat
                CharacterStat s = fis[i].GetValue(stats) as CharacterStat;
                // Getting EquipmentMod
                FieldInfo fis2 = Members.GetField(equippedItem.statMods, fis[i].Name+"Mod");
                StatModifier sM = fis2.GetValue(equippedItem.statMods) as StatModifier;
                // Adding mod only if it is not 0
                if(sM.Value != 0)
                {

                    s.AddModifier(sM);
                    float f = s.Value;
                }
            }
        }
    }
}

Doing the same for unequip does not seem to work as it doesn't remove the modifier from the list in CharacterStat.

In case you were wondering my Members class below:

public class Members 
{
    public static FieldInfo GetField(System.Object obj, string name)
    {
        Type t = obj.GetType();
        FieldInfo fis = t.GetField(name, BindingFlags.Instance | BindingFlags.Public);
        return fis;
    }
    public static FieldInfo[] GetFields(System.Object obj)
    {
        Type t = obj.GetType();
        FieldInfo[] fis = t.GetFields(BindingFlags.ExactBinding | BindingFlags.Instance | BindingFlags.Public);
        return fis;
    }
}

Straight copy and paste of both CharacterStat and StatModifier from Kryzarel video:

using System;

public enum StatModifierType
{
    Flat = 100,
    PercentAdd = 200,
    PercentMult = 300,
}

public class StatModifier
{
    public readonly float Value;
    public readonly StatModifierType Type;
    public readonly int Order;
    public readonly object Source;

    public StatModifier(float value, StatModifierType type, int order, object source)
    {
        Value = value;
        Type = type;
        Order = order;
        Source = source;
    }
    // Requires value and type, leaving order and source at default values
    public StatModifier(float value, StatModifierType type) : this(value, type, (int)type, null) {}
    // Requires value and type and order, leaving source at default value
    public StatModifier(float value, StatModifierType type, int order) : this(value, type, order, null) {}
    // Requires value and type and source, leaving order at default value
    public StatModifier(float value, StatModifierType type, object source) : this(value, type, (int)type, source) {}

}

..................................

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

[Serializable]
public class CharacterStat
{
    /*-------------------------------------------------------------------------------------------------------------------------
                VARIABLES                                                                                   
    -------------------------------------------------------------------------------------------------------------------------*/
    public float BaseValue;
    protected float lastBaseValue = float.MinValue;
    protected readonly List<StatModifier> statModifiers;
    public readonly ReadOnlyCollection<StatModifier> StatModifiers;
    protected bool isDirty = true;
    protected float _value;
    /*-------------------------------------------------------------------------------------------
                PROPERTIES - CONSTRUCTOR                                                                                   
    -------------------------------------------------------------------------------------------*/
    public virtual float Value{ 
        get{
            if(isDirty || BaseValue != lastBaseValue)
            {
                lastBaseValue = BaseValue;
                _value = CalculateFinalValue();
                isDirty = false;
            }
            return _value;
        }
    }
    /*-------------------------------------------------------------------------------------------------------------------------
                METHODS                                                                                 
    -------------------------------------------------------------------------------------------------------------------------*/ 
    /*-------------------------------------------------------------------------------------------
                METHODS - CONSTRUCTOR                                                                                   
    -------------------------------------------------------------------------------------------*/
    public CharacterStat()
    {
        statModifiers = new List<StatModifier>();
        StatModifiers = statModifiers.AsReadOnly();
    }
    public CharacterStat(float baseValue) : this()
    {
        BaseValue = baseValue;
    }
    /*-------------------------------------------------------------------------------------------
                METHODS - ADD MODIFIER                                                                                   
    -------------------------------------------------------------------------------------------*/
    public virtual void AddModifier(StatModifier mod)
    {
        isDirty = true;
        statModifiers.Add(mod);
        statModifiers.Sort(CompareModifierOrder);
    }
    /*-------------------------------------------------------------------------------------------
                METHODS - ADD MODIFIER                                                                                   
    -------------------------------------------------------------------------------------------*/
    protected virtual int CompareModifierOrder(StatModifier a, StatModifier b)
    {
        if(a.Order < b.Order)
            return -1;
        else if(a.Order > b.Order)
            return 1;
        return 0; // if(a.Order == b.Order)
    }
    /*-------------------------------------------------------------------------------------------
                METHODS - REMOVE MODIFIER                                                                                   
    -------------------------------------------------------------------------------------------*/
    public virtual bool RemoveModifier(StatModifier mod)
    {
        if(statModifiers.Remove(mod))
        {
            isDirty = true;
            return true;
        }
        return false;
    }
    /*-------------------------------------------------------------------------------------------
                METHODS - REMOVE MODIFIER                                                                                   
    -------------------------------------------------------------------------------------------*/
    public virtual bool RemoveAllModifiersFromSource(object source)
    {
        bool didRemove = false;
        for(int i=statModifiers.Count-1; i<=0; i--) // Treversing through list
        {
            if(statModifiers[i].Source == source)
            {
                isDirty = true;
                didRemove = true;
                statModifiers.RemoveAt(i);
            }
        }
        return didRemove;
    }
    /*-------------------------------------------------------------------------------------------
                METHODS - UPDATE STAT                                                                                   
    -------------------------------------------------------------------------------------------*/
    protected virtual float CalculateFinalValue()
    {
        float finalValue = BaseValue;
        float sumPercentAdd = 0;
        for(int i=0; i<statModifiers.Count; i++)
        {
            StatModifier mod = statModifiers[i];
            if(mod.Type == StatModifierType.Flat)
            {
                finalValue += mod.Value;
            }
            else if(mod.Type == StatModifierType.PercentAdd)
            {
                sumPercentAdd += mod.Value;
                if(i+1 >= statModifiers.Count || statModifiers[i+1].Type != StatModifierType.PercentAdd)
                {
                    finalValue *= 1 + sumPercentAdd;
                    sumPercentAdd = 0;
                }
            }
            else if(mod.Type == StatModifierType.PercentMult)
            {
                finalValue *= 1 + mod.Value;
            }
        }
        return (float)Math.Round(finalValue, 4);
    }
}
0 Answers
Related