Files
FablishRPG/Assets/Scripts/PlayerStats.cs

145 lines
4.0 KiB
C#
Raw Normal View History

2026-09-29 16:11:54 +01:00
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);
}
}
}
}
[HideInInspector] public bool isBlocking = false;
[HideInInspector] public float currentBlockReduction = 0f;
2026-09-29 16:11:54 +01:00
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);
}
/// <summary>
/// Attempts to use stamina.
/// </summary>
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();
}
}