Skip to content
Snippets Groups Projects
StatsManager.cs 6.29 KiB
Newer Older
using System.Collections.Generic;
using UnityEngine;

public enum UpgradeTypes
{
    ENEMY_HEALTH,
    ENEMY_DAMAGE,
    ENEMY_ARMOR,
    MANA_COST,
}

public enum FighterTypes
public struct FighterStats
{
    public float healthMultiplier;
    public float damageMultiplier;
    public float armorMultiplier;
}

public class UpgradeData
{
    public Upgrade upgrade;
    public int count;

    // How much it costs to purchase another one of this upgrade
    public int GetNextUpgradeCost()
        return StatsManager.instance.AdjustManaCost(GetUnadjustedNextUpgradeCost());
    }

    public float GetTotalEffectMultiplier()
    {
        return 1 + count * upgrade.effectMultiplier;
    }

    // You probably shouldn't call this outside this file.
    public int GetUnadjustedNextUpgradeCost()
    {
        return (int)(upgrade.baseCost * Mathf.Pow(1 + upgrade.costMultiplier, count));
public interface IManaChangeCallback
{
    void OnManaChanged(int oldValue, int newValue);
}

Adrian Paschkowski's avatar
Adrian Paschkowski committed
// Provides the current Statistics (buffs) for supported Fighter types as well as
// Mana storage and management. Allows scripts to buy Upgrade or otherwise spend Mana.
public class StatsManager : MonoBehaviour, IRoundCallback
{

    public static StatsManager instance { get; private set; }

    [SerializeField] int currentMana;
    int manaAtRoundStart;
Adrian Paschkowski's avatar
Adrian Paschkowski committed
    [SerializeField, Tooltip("When the AntiPlayer receives damage, how much of that damage is converted to Mana")]
    float antiPlayerDamageManaMultiplier = 100f;
    [SerializeField, Tooltip("When the AntiPlayer dies, how much mana to give")]
    int antiPlayerDeathMana = 1000;
    [SerializeField] List<Upgrade> availableUpgrades;
    // The currently active statistics for each fighter type
    public Dictionary<FighterTypes, FighterStats> fighterStats = new Dictionary<FighterTypes, FighterStats>();

Adrian Paschkowski's avatar
Adrian Paschkowski committed
    // Information about currently available and purchased Enemy upgrades. Should only be read, not modified.
    public Dictionary<UpgradeTypes, UpgradeData> upgrades = new Dictionary<UpgradeTypes, UpgradeData>();
    // Want to be notified whenever the current Mana amount changes?
    public List<IManaChangeCallback> manaChangeCallbacks = new List<IManaChangeCallback>();

    public int GetMana()
    {
        return currentMana;
    }

    // Adjusts the given Mana cost based on the amount of Mana cost upgrades currently bought.
    public int AdjustManaCost(int cost)
    {
        return (int)(cost * upgrades[UpgradeTypes.MANA_COST].GetTotalEffectMultiplier());
    }

    public int GetNextUpgradeCost(UpgradeTypes type)
    {
        return upgrades[type].GetNextUpgradeCost();
    }

    // Buys an upgrade, spending the required amount of Mana in the process. Returns false if not enough Mana is available.
    public bool BuyUpgrade(UpgradeTypes type)
    {
        if (!ModifyMana(-GetNextUpgradeCost(type)))
        {
            return false;
        }
        upgrades[type].count++;
Adrian Paschkowski's avatar
Adrian Paschkowski committed
        RecalculateEnemyStats();
    // Add (positive value) or spend (negative value) Mana. Returns false if not enough Mana is available to spend.
    public bool ModifyMana(int delta)
    {
        if (!CanModifyMana(delta))
        var previousMana = currentMana;
        currentMana += delta;
        if (delta != 0)
        {
            manaChangeCallbacks.ForEach(c => c.OnManaChanged(previousMana, currentMana));
        }
    // If `delta` is negative, returns this amount of Mana can be spent. If `delta` is positive, this will always return `true`.
    public bool CanModifyMana(int delta)
    {
        return currentMana + delta >= 0;
    }

Adrian Paschkowski's avatar
Adrian Paschkowski committed
    // Adds Mana based on the amount of damage the AntiPlayer has taken
    public void AddDamageBasedMana(int damage, bool death = false)
    {
        if (death)
        {
            ModifyMana(antiPlayerDeathMana);
        }
        else
        {
            ModifyMana((int)(damage * antiPlayerDamageManaMultiplier));
        }
    }

Adrian Paschkowski's avatar
Adrian Paschkowski committed
    // How much a specific Enemy stat is buffed based on how many Upgrades have already been purchased
    public float GetTotalEffectMultiplier(UpgradeTypes type)
    {
        return upgrades[type].GetTotalEffectMultiplier();
    }

    public void UpgradeAntiPlayer()
    {
        var playerStats = fighterStats[FighterTypes.ANTI_PLAYER];
        playerStats.healthMultiplier += 0.2f;
        playerStats.damageMultiplier += 0.2f;
        playerStats.armorMultiplier += 0.1f;
        fighterStats[FighterTypes.ANTI_PLAYER] = playerStats;
    }

Adrian Paschkowski's avatar
Adrian Paschkowski committed
    void RecalculateEnemyStats()
        var enemyStats = fighterStats[FighterTypes.ENEMY];
        enemyStats.healthMultiplier = upgrades[UpgradeTypes.ENEMY_HEALTH].GetTotalEffectMultiplier();
        enemyStats.damageMultiplier = upgrades[UpgradeTypes.ENEMY_DAMAGE].GetTotalEffectMultiplier();
        enemyStats.armorMultiplier = upgrades[UpgradeTypes.ENEMY_ARMOR].GetTotalEffectMultiplier();
        fighterStats[FighterTypes.ENEMY] = enemyStats;
    }

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
        DontDestroyOnLoad(gameObject);

        foreach (Upgrade upgrade in availableUpgrades)
        {
            UpgradeData upgradeData = new UpgradeData();
            upgradeData.upgrade = upgrade;
            upgradeData.count = 0;
            upgrades.Add(upgrade.type, upgradeData);
        }

        fighterStats.Add(FighterTypes.ANTI_PLAYER, new FighterStats()
        {
            healthMultiplier = 1f,
            damageMultiplier = 1f,
            armorMultiplier = 1f,
        });
        fighterStats.Add(FighterTypes.ENEMY, new FighterStats()
        {
            healthMultiplier = 1f,
            damageMultiplier = 1f,
            armorMultiplier = 1f,
        });

    void Start()
    {
        RoundController.instance.roundCallbacks.Add(this);
    }

    public void OnRoundStart()
    {
        manaAtRoundStart = currentMana;
    }

    public void OnRoundEnd(bool won)
    {
        if (!won)
        {
            // Reset current Mana back to start value if round was lost
            var gainedMana = currentMana - manaAtRoundStart;
            ModifyMana(-gainedMana);
        }
    }