Batch 1 - Scripts
This commit is contained in:
213
Assets/New Lowpoly Models/Scripts/Player/Health.cs
Normal file
213
Assets/New Lowpoly Models/Scripts/Player/Health.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user