using UnityEngine; using UnityEngine.Events; public class PlayerStats : MonoBehaviour { [Header("Health")] public float maxHealth = 100f; public float currentHealth; [Header("Mana")] public float maxMana = 100f; public float currentMana; [Header("Stamina")] public float maxStamina = 100f; public float currentStamina; public float staminaRegenRate = 15f; public float staminaRegenDelay = 1.5f; [Header("Events")] public UnityEvent onDeath; private float _lastStaminaUseTime; private bool _isDead; private void Awake() { currentHealth = maxHealth; currentMana = maxMana; currentStamina = maxStamina; } public float sprintStaminaDrainRate = 10f; [Tooltip("Optional: Drag the InputReader here to automatically drain stamina when sprinting")] public Synty.AnimationBaseLocomotion.Samples.InputSystem.InputReader inputReader; private bool _isSprinting; private float _regenPauseEndTime; [HideInInspector] public float staminaRegenMultiplier = 1f; public void PauseStaminaRegen(float seconds) { _regenPauseEndTime = Time.time + seconds; } private void OnEnable() { if (inputReader != null) { inputReader.onSprintActivated += HandleSprintStart; inputReader.onSprintDeactivated += HandleSprintStop; } } private void OnDisable() { if (inputReader != null) { inputReader.onSprintActivated -= HandleSprintStart; inputReader.onSprintDeactivated -= HandleSprintStop; } } private void HandleSprintStart() => _isSprinting = true; private void HandleSprintStop() => _isSprinting = false; private void Update() { if (_isDead) return; // Drain stamina if sprinting and moving if (_isSprinting && inputReader != null && inputReader._movementInputDetected) { UseStamina(sprintStaminaDrainRate * Time.deltaTime); // If we run out of stamina while sprinting, you might want to force walk here if (currentStamina <= 0) { // Force sprint off via the reader _isSprinting = false; // Note: To perfectly force the Synty controller to stop running, // you would normally call a method on the SamplePlayerAnimationController. } } else { // Regenerate stamina if we haven't used it recently and not paused if (Time.time > _lastStaminaUseTime + staminaRegenDelay && Time.time > _regenPauseEndTime) { if (currentStamina < maxStamina) { currentStamina += (staminaRegenRate * staminaRegenMultiplier) * Time.deltaTime; currentStamina = Mathf.Clamp(currentStamina, 0f, maxStamina); } } } } public void TakeDamage(float amount) { if (_isDead) return; currentHealth -= amount; currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth); if (currentHealth <= 0) { Die(); } } public void Heal(float amount) { if (_isDead) return; currentHealth += amount; currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth); } /// /// Attempts to use stamina. /// public void UseStamina(float amount) { currentStamina -= amount; currentStamina = Mathf.Clamp(currentStamina, 0f, maxStamina); _lastStaminaUseTime = Time.time; } public bool HasStaminaPercentage(float percentage) { return currentStamina >= (maxStamina * percentage); } private void Die() { _isDead = true; Debug.Log("Player has died!"); onDeath?.Invoke(); } }