Files
CartoonFPS/Assets/Scripts/BaseAIController.cs
2025-08-06 23:18:38 +01:00

187 lines
4.7 KiB
C#

using UnityEngine;
using Akila.FPSFramework;
public enum TargetType
{
None,
Enemy,
Player,
PatrolPoint
}
public abstract class BaseAIController : MonoBehaviour
{
[Header("Movement & Combat")]
public float moveSpeed = 5f;
public float chaseRange = 15f;
public float stopCloseRange = 4f;
public float strafeAmount;
public float pointWaitTimer = 3f;
public float currentHealth = 25f;
public float waitToDisappear = 4f;
public float damageAmount = 10f;
[Header("Components")]
public Rigidbody theRB;
public Animator anim;
[Header("Patrol")]
public Transform[] PatrolPoints;
protected int currentPatrolPoint;
public Transform pointsHolder;
protected float waitCounter;
protected bool isDead;
protected float attackCooldown = 1f;
protected float attackTimer = 0f;
protected FirstPersonController player;
protected Damageable playerDamageable;
protected virtual void Start()
{
player = FindFirstObjectByType<FirstPersonController>();
if (player != null)
{
playerDamageable = player.GetComponent<Damageable>();
}
strafeAmount = Random.Range(-0.75f, 0.75f);
if (pointsHolder != null)
{
pointsHolder.SetParent(null);
}
waitCounter = Random.Range(0.75f, 1.25f) * pointWaitTimer;
attackTimer = 0f;
}
protected void HandleDeath()
{
waitToDisappear -= Time.deltaTime;
if (waitToDisappear <= 0)
{
transform.localScale = Vector3.MoveTowards(transform.localScale, Vector3.zero, Time.deltaTime * 2f);
if (transform.localScale.magnitude < 0.1f)
{
Destroy(gameObject);
if (pointsHolder != null)
{
Destroy(pointsHolder.gameObject);
}
}
}
}
protected void UpdateTimers()
{
attackTimer -= Time.deltaTime;
}
protected bool ValidatePlayerReferences()
{
return player != null && playerDamageable != null;
}
protected void StopMovement()
{
theRB.linearVelocity = Vector3.zero;
anim.SetFloat("speed", 0f);
}
protected void LookAt(Transform target)
{
if (target != null)
{
transform.LookAt(new Vector3(target.position.x, transform.position.y, target.position.z));
}
}
protected void MoveTowardsTarget(Transform target, float speedMultiplier)
{
if (target != null)
{
LookAt(target);
theRB.linearVelocity = (transform.forward + transform.right * strafeAmount) * moveSpeed;
anim.SetFloat("speed", speedMultiplier);
}
}
protected void AttackTarget()
{
theRB.linearVelocity = Vector3.zero;
anim.SetFloat("speed", 0f);
if (attackTimer <= 0f)
{
anim.SetTrigger("attack");
attackTimer = attackCooldown;
}
}
protected void HandlePatrolling()
{
if (PatrolPoints.Length > 0)
{
float distanceToPatrolPoint = Vector3.Distance(transform.position,
new Vector3(PatrolPoints[currentPatrolPoint].position.x, transform.position.y, PatrolPoints[currentPatrolPoint].position.z));
if (distanceToPatrolPoint < 0.25f)
{
WaitAtPatrolPoint();
}
else
{
MoveToPatrolPoint();
}
}
else
{
StopMovement();
}
}
protected void WaitAtPatrolPoint()
{
waitCounter -= Time.deltaTime;
StopMovement();
if (waitCounter <= 0)
{
MoveToNextPatrolPoint();
}
}
protected void MoveToNextPatrolPoint()
{
currentPatrolPoint++;
if (currentPatrolPoint >= PatrolPoints.Length)
{
currentPatrolPoint = 0;
}
waitCounter = Random.Range(0.75f, 1.25f) * pointWaitTimer;
}
protected void MoveToPatrolPoint()
{
MoveTowardsTarget(PatrolPoints[currentPatrolPoint], 0.5f); // Walking speed
}
protected void PreserveVerticalVelocity(float yStore)
{
theRB.linearVelocity = new Vector3(theRB.linearVelocity.x, yStore, theRB.linearVelocity.z);
}
public virtual void TakeDamage(float damageToTake)
{
currentHealth -= damageToTake;
if (currentHealth <= 0)
{
anim.SetTrigger("dead");
isDead = true;
theRB.linearVelocity = Vector3.zero;
theRB.isKinematic = true;
GetComponent<Collider>().enabled = false;
}
}
}