Files
DeviantMobile-Rohan/Assets/New Lowpoly Models/Scripts/Health.cs
2026-06-26 22:41:39 +05:30

213 lines
5.1 KiB
C#

using Cinemachine;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
public class Health : MonoBehaviour
{
public float currentHealth;
public float maxHealth = 100f;
// Event used by UI or other systems to react to health changes
public event Action<float, float> OnHealthChanged;
private CharacterController controller;
public bool isHit;
public bool isDead;
[SerializeField] private float knockbackForce = 4f;
[SerializeField] private float knockbackDuration = 0.2f;
private Vector3 knockbackVelocity;
private float knockbackTimer;
private NavMeshAgent agent;
//[SerializeField] private float knockbackForce = 6f;
//[SerializeField] private float knockbackDuration = 0.2f;
//private Vector3 knockbackVelocity;
//private float knockbackTimer;
void Awake()
{
controller = GetComponent<CharacterController>();
agent = GetComponent<NavMeshAgent>();
}
void Start()
{
currentHealth = maxHealth;
OnHealthChanged?.Invoke(currentHealth, maxHealth);
}
void Update()
{
if (isDead) return;
if (knockbackTimer > 0)
{
knockbackTimer -= Time.deltaTime;
// ONLY move via CharacterController if it is still enabled
if (controller != null && controller.enabled)
{
controller.Move(knockbackVelocity * Time.deltaTime);
}
// TEMP stop agent movement only if agent is enabled and active
if (agent != null && agent.enabled && agent.isOnNavMesh)
{
agent.isStopped = true;
}
}
else
{
// Resume AI movement only if agent is enabled and active
if (agent != null && agent.enabled && agent.isOnNavMesh)
{
agent.isStopped = false;
}
}
}
public void TakeDamage(float amount, string bodyPart)
{
if (isDead) return;
currentHealth = Mathf.Clamp(currentHealth - amount, 0, maxHealth);
OnHealthChanged?.Invoke(currentHealth, maxHealth);
// PLAY ENEMY GRUNT SOUND
if (AudioManager.Instance != null)
{
AudioManager.Instance.PlayEnemyHit();
}
PlayerControllerNewRohan player = GetComponent<PlayerControllerNewRohan>();
if (player != null)
{
player.CancelAttack();
}
//SimpleEnemyAI enemy = GetComponent<SimpleEnemyAI>();
//if (enemy != null)
//{
// enemy.CancelAttackAndHit(bodyPart);
//}
var receiver = GetComponent<IDamageReceiver>();
receiver?.OnDamageTaken(bodyPart);
// DEATH CHECK
if (currentHealth <= 0)
{
Die();
}
}
void Die()
{
if (isDead) return;
isDead = true;
DisableAfterDeath();
CashManager cashManager = GetComponent<CashManager>();
if (cashManager != null)
{
cashManager.DropAllCash();
}
Animator anim = GetComponent<Animator>();
if (anim != null)
{
anim.SetTrigger("Death");
}
// STOP NAVMESH
// STOP NAVMESH
if (agent != null && agent.enabled)
{
if (agent.isOnNavMesh)
{
agent.isStopped = true;
agent.ResetPath();
agent.velocity = Vector3.zero;
}
agent.enabled = false;
}
// DISABLE PLAYER CONTROLLER
PlayerControllerNewRohan player = GetComponent<PlayerControllerNewRohan>();
if (player != null)
{
player.enabled = false;
}
// DISABLE ENEMY AI
//SimpleEnemyAI enemy = GetComponent<SimpleEnemyAI>();
//if (enemy != null)
//{
// enemy.enabled = false;
//}
// OPTIONAL
CharacterController cc = GetComponent<CharacterController>();
if (cc != null)
{
cc.enabled = false;
}
// Destroy after animation
Destroy(gameObject, 2f);
}
public void ApplyKnockback(Vector3 direction, float forceMultiplier = 1f)
{
if (knockbackTimer > 0) return; // prevent stacking
direction.Normalize();
// Add slight upward push (optional but feels better)
Vector3 finalDir = direction;
knockbackVelocity = finalDir * knockbackForce * forceMultiplier;
knockbackTimer = knockbackDuration;
}
void DisableAfterDeath()
{
gameObject.tag = "Untagged";
Collider[] colliders = GetComponentsInChildren<Collider>();
foreach (Collider col in colliders)
{
col.enabled = false;
}
SimpleTeamAI ai = GetComponent<SimpleTeamAI>();
if (ai != null)
ai.enabled = false;
MonoBehaviour[] scripts = GetComponentsInChildren<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
if (script != this && script.GetType() != typeof(Animator))
script.enabled = false;
}
}
}