using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public class CharacterStats : MonoBehaviour { [Header("Identity & Level")] [SerializeField] private string characterName = "Character"; [SerializeField] private int level = 1; [Header("Health Stats")] [SerializeField] private float maxHealth = 100f; [SerializeField] private float currentHealth; [SerializeField] private float healthRegenRate = 0.5f; // per second [Header("Mana Stats")] [SerializeField] private float maxMana = 50f; [SerializeField] private float currentMana; [SerializeField] private float manaRegenRate = 1.0f; // per second [Header("Stamina Stats")] [SerializeField] private float maxStamina = 100f; [SerializeField] private float currentStamina; [SerializeField] private float staminaRegenRate = 5.0f; // per second [Header("Combat Attributes")] [SerializeField] private float baseDamage = 10f; [SerializeField] private float attackSpeed = 1.0f; // Attacks per second [SerializeField] private float attackRange = 2.0f; [SerializeField] private float armor = 0f; [SerializeField] private float moveSpeedMultiplier = 1.0f; [Header("Equipment")] [SerializeField] private string currentWeapon = "Unarmed"; [SerializeField] private GameObject weaponPrefab; [Header("Rewards & Drops (For NPCs / Enemies)")] [SerializeField] private int expReward = 50; [SerializeField] private int goldReward = 25; [SerializeField] private List dropReward = new List(); [Header("Events")] public UnityEvent onHealthChanged; // current, max public UnityEvent onManaChanged; // current, max public UnityEvent onStaminaChanged; // current, max public UnityEvent onDeath; // killer public bool IsDead { get; private set; } = false; private void Awake() { currentHealth = maxHealth; currentMana = maxMana; currentStamina = maxStamina; } private void Update() { if (IsDead) return; // Passive Regeneration RegenerateStats(); } private void RegenerateStats() { if (currentHealth < maxHealth && healthRegenRate > 0) { Heal(healthRegenRate * Time.deltaTime); } if (currentMana < maxMana && manaRegenRate > 0) { RestoreMana(manaRegenRate * Time.deltaTime); } if (currentStamina < maxStamina && staminaRegenRate > 0) { RestoreStamina(staminaRegenRate * Time.deltaTime); } } // --- Damage & Healing Methods --- public void TakeDamage(float damageAmount, GameObject attacker = null) { if (IsDead) return; // Apply Armor reduction float netDamage = Mathf.Max(damageAmount - armor, 1.0f); currentHealth -= netDamage; currentHealth = Mathf.Clamp(currentHealth, 0, maxHealth); onHealthChanged?.Invoke(currentHealth, maxHealth); Debug.Log($"[{gameObject.name}] Took {netDamage} damage from {(attacker != null ? attacker.name : "Unknown")}. HP: {currentHealth}/{maxHealth}"); if (currentHealth <= 0) { Die(attacker); } } public void Heal(float amount) { if (IsDead) return; currentHealth += amount; currentHealth = Mathf.Clamp(currentHealth, 0, maxHealth); onHealthChanged?.Invoke(currentHealth, maxHealth); } // --- Mana Methods --- public bool UseMana(float amount) { if (currentMana >= amount) { currentMana -= amount; onManaChanged?.Invoke(currentMana, maxMana); return true; } return false; } public void RestoreMana(float amount) { currentMana = Mathf.Clamp(currentMana + amount, 0, maxMana); onManaChanged?.Invoke(currentMana, maxMana); } // --- Stamina Methods --- public bool UseStamina(float amount) { if (currentStamina >= amount) { currentStamina -= amount; onStaminaChanged?.Invoke(currentStamina, maxStamina); return true; } return false; } public void RestoreStamina(float amount) { currentStamina = Mathf.Clamp(currentStamina + amount, 0, maxStamina); onStaminaChanged?.Invoke(currentStamina, maxStamina); } // --- Death Handling --- private void Die(GameObject killer) { IsDead = true; Debug.Log($"[{gameObject.name}] has been defeated!"); onDeath?.Invoke(killer); // Spawn Loot Drops if assigned SpawnLoot(); } private void SpawnLoot() { if (dropReward == null || dropReward.Count == 0) return; foreach (GameObject lootPrefab in dropReward) { if (lootPrefab != null) { Vector3 spawnOffset = new Vector3(UnityEngine.Random.Range(-0.5f, 0.5f), 0.2f, UnityEngine.Random.Range(-0.5f, 0.5f)); Instantiate(lootPrefab, transform.position + spawnOffset, Quaternion.identity); } } } // --- Getters & Setters --- public string CharacterName => characterName; public int Level => level; public float HealthPercentage => currentHealth / maxHealth; public float ManaPercentage => currentMana / maxMana; public float StaminaPercentage => currentStamina / maxStamina; public float AttackSpeed => attackSpeed; public float AttackRange => attackRange; public float BaseDamage => baseDamage; public string CurrentWeapon => currentWeapon; public int ExpReward => expReward; public int GoldReward => goldReward; }