Files
TopDown/Assets/Scripts/CharacterStats.cs

187 lines
5.7 KiB
C#
Raw Permalink Normal View History

2026-08-04 16:56:27 +01:00
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<GameObject> dropReward = new List<GameObject>();
[Header("Events")]
public UnityEvent<float, float> onHealthChanged; // current, max
public UnityEvent<float, float> onManaChanged; // current, max
public UnityEvent<float, float> onStaminaChanged; // current, max
public UnityEvent<GameObject> 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($"<color=red>[{gameObject.name}] has been defeated!</color>");
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;
}