Stats not calculating

I am already bad about rambling on in my posts, so I will try my best to be concise.

I have integrated all of the inventory/stats scripts into my main project. At least, the parts that I intend on using. My player does not have base stats (apart from base health, mana, speed, composure, and composure regen rate) so I was able to combine BaseStats with Stat. Ignore that Health and Composure still look for “MaxXXX” instead of Base, because I haven’t overhauled them from the basic pre-modifier versions yet. The one of concern is Mana as I only just now integrated it at all and was doing it side-by-side with modifiers to make sure it all works:

public class StatsHandler : MonoBehaviour
{
    public float GetStat(Stat stat)
    {
        return (GetBaseStat(stat) + GetAdditiveModifier(stat)) * (1 + GetPercentageModifier(stat) / 100);
    }

    private float GetBaseStat(Stat stat)
    {
        if (stat == Stat.Health) return GetComponent<Health>().GetMaxHealth();
        if (stat == Stat.Mana) return GetComponent<Mana>().GetBaseMana();
        if (stat == Stat.Composure) return GetComponent<Composure>().GetMaxComposure();
        if (stat == Stat.ComposureRegen) return GetComponent<Composure>().GetComposureICRegen();
        if (stat == Stat.MovementSpeed)
        {
            if (gameObject.CompareTag("Player")) return GetComponent<PlayerStateMachine>().FreeLookMovementSpeed;
            else return GetComponent<EnemyStateMachine>().MovementSpeed;
        }
        
        return 0;
    }

    private float GetAdditiveModifier(Stat stat)
    {
        float total = 0;
        int x = 0;
        foreach (IModifierProvider provider in GetComponents<IModifierProvider>())
        {
            //Debug.Log(x++);
            foreach (float modifier in provider.GetAdditiveModifiers(stat))
            {
                Debug.Log(stat.ToString() + ": " + modifier);
                total += modifier;
            }
        }
        x = 0;
        return total;
    }

    private float GetPercentageModifier(Stat stat)
    {
        float total = 0;
        foreach (IModifierProvider provider in GetComponents<IModifierProvider>())
        {
            foreach (float modifier in provider.GetPercentageModifiers(stat))
            {
                total += modifier;
            }
        }
        return total;
    }
}

I have that int x in there for debugging purposes and confirmed it was always 0. No providers found. Otherwise, the modifiers work exactly like they did in the RPG course. It actually took me quite a bit of time to remember how this all worked. GetComponents puzzled me for a long time and then I went and traced it all the way through and remembered how this works.

Long story short, I have made a StatsEquippableItem hat that should be adding 10 to mana. I do have different Stat names and different EquipmentSlot names. But I was able to debug out that it does know when I am equipping the item. It spat out the name of the item.

You can also see that I have added some things to various Item SO’s, but the meat of it remains the same. But it refuses to cooperate. I added some other debug lines and see that it is just plain not finding any “providers” in the GetAdditiveModifier method. I have an update method that looks for a keypress that I try before and after equipping the item. I’ve checked various things.

The ONLY thing I am seeing that is weird is that there are clearly two Equipment.cs copies out there. I have added [DisallowMultipleComponent] and still two show up. I cannot find a second instance of that script ANYWHERE in my project. I have searched the hiearchy and only find the one I expect to… on player. I’ve checked prefabs and scene instances. Every time I get two debug outputs. One that complains about Null references a lot, clearly, and one that will give me some info. Trying to output something like:

IModifierProvider testM = GetItemInSlot(EquipLocation.Head) as IModifierProvider;
Debug.Log(testM.ToString());

Doesn’t really give me anything useful, but it does give me SOMETHING.

I am truly at a loss here. I spent a couple hours last night that I hadn’t even planned on coding at ALL but once I found this to not work I was sucked in. As far as I am aware, I am not missing any scripts that would be vital. I have not implemented the Saving System yet so I did comment out the body of those methods in Equipment but that shouldn’t make a difference anyway.

Any help at all… Any debugging tips… Hell I’ll send someone my scripts if it helps. Tell me what you need from me to help track this down and you are my hero forever.

Also here is Mana:

    public int GetMaxMana()
    {
        maxMana = Mathf.RoundToInt(statsHandler.GetStat(Stat.Mana));
        return maxMana;
    }

(Also please ignore the circular dependencies… LOL… I just realized StatsHandler calls Mana during that run… I’ll worry about efficiency once it is working… thinking probably an optional parameter for GetStat that overrides the BaseStat part of the equation with it… yeah… that sounds perfect)

You should only be getting the Stat modifiers from elements on same GameObject… so any extra StatsEquipment would have to be on the same GameObject as the StatsHandler.

Paste in your StatsEquipment.cs script and we’ll take a look.

You should know with this snippet of code, that if there is nothing equipped in the Head slot of your StatsEquipment, this will yield a null reference error (since testM will be null when you Debug.Log it out).

AFTER equipping that code is still not helpful. I’ll grab it in a sec… But here is StatsEquipment… Like it was out of the box

public class StatsEquipment : Equipment, IModifierProvider
{
    IEnumerable<float> IModifierProvider.GetAdditiveModifiers(Stat stat)
    {
        foreach (var slot in GetAllPopulatedSlots())
        {
            var item = GetItemInSlot(slot) as IModifierProvider;
            if (item == null) continue;

            foreach (float modifier in item.GetAdditiveModifiers(stat))
            {
                UnityEngine.Debug.Log(modifier.ToString());
                yield return modifier;
            }
        }
    }

    IEnumerable<float> IModifierProvider.GetPercentageModifiers(Stat stat)
    {
        foreach (var slot in GetAllPopulatedSlots())
        {
            var item = GetItemInSlot(slot) as IModifierProvider;
            if (item == null) continue;

            foreach (float modifier in item.GetPercentageModifiers(stat))
            {
                yield return modifier;
            }
        }
    }

}

And here is what that debug log for testM is:
image

Which I swear wasn’t what I was thinking of. It was a different Debug.Log… Anyway… THAT makes it sound like it should be working other than the obvious duplicate copy of Equipment.cs I can’t find.

StatsHandler, StatsEquipment, and Equipment.cs are on the same GO… The player:

image

Sigh…

I was supposed to get rid of regular Equipment.cs once we made StatsEquipment.cs…

That solves ALL mysteries…

I’ll see myself out.

You can actually avoid this in future… since Equipment is generally as useless as a politician once you have StatsEquipment…
Go into Equipment.cs and change the declaration to

public abstract class Equipment: MonoBehaviour

By making it abstract, you won’t be able to add it to any GameObject, then you can only add a StatsEquipment.

2 Likes

This is the issue with having done the RPG course before 3rd person traversal. While it was only a couple months ago, it was a lot of info and I binged it. Then switching gears with 3rd person traversal. Completely different styles from our beloved instructors and massively different types of things we were doing… My brain just blanked on the lovely progression that we got from the RPG course.

I am taking a “What won’t irritate me now” approach to this project. So jumping around a lot to not burn out. I legit hadn’t planned on messing with the stats at all but randomly decided it would be “easy.” I suppose had I waited longer it would have been even worse.

I look forward to my next catastrophe. Dare I start migrating abilities in? But hey! Already fixed my circular dependency here. StatsHandler is nice and lean now. I just have to remember those 5 or so stats that are special and actually have bases for when I do a stats screen.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms