277 lines
8.7 KiB
C#
277 lines
8.7 KiB
C#
//using UnityEngine;
|
|
//using UnityEngine.AI;
|
|
//using System.Collections;
|
|
|
|
///// <summary>
|
|
///// EnemyAIController - AI controller for ENEMY team characters.
|
|
///// These AI characters fight AGAINST the player, targeting player team members.
|
|
///// Used in Cash System mode for enemy team AI.
|
|
///// </summary>
|
|
//[RequireComponent(typeof(TeamMember))]
|
|
//public class EnemyAIController : MonoBehaviour
|
|
//{
|
|
// [Header("AI State")]
|
|
// [SerializeField] private AIState currentState = AIState.Idle;
|
|
|
|
// [Header("Detection Settings")]
|
|
// [SerializeField] private float detectionRange = 15f;
|
|
// [SerializeField] private float attackRange = 2f;
|
|
// [SerializeField] private float aggroRange = 10f;
|
|
|
|
// [Header("Behavior Settings")]
|
|
// [SerializeField] private float decisionInterval = 0.5f;
|
|
// [SerializeField] private bool aggressive = true;
|
|
|
|
// [Header("References")]
|
|
// private TeamMember teamMember;
|
|
// private NavMeshAgent navAgent;
|
|
// private Animator animator;
|
|
// private CharacterAttacks characterAttacks;
|
|
|
|
// // Combat
|
|
// private TeamMember currentTarget;
|
|
// private float lastAttackTime;
|
|
// private float attackCooldown = 1.5f;
|
|
|
|
// // Cash System integration
|
|
// private CashCarrier cashCarrier;
|
|
// private CashSystemAI cashAI;
|
|
|
|
// public enum AIState
|
|
// {
|
|
// Idle,
|
|
// Patrol,
|
|
// ChaseEnemy,
|
|
// Attack,
|
|
// CollectCash,
|
|
// DepositCash,
|
|
// StealCash,
|
|
// Retreat
|
|
// }
|
|
|
|
// private void Awake()
|
|
// {
|
|
// teamMember = GetComponent<TeamMember>();
|
|
// navAgent = GetComponent<NavMeshAgent>();
|
|
// animator = GetComponent<Animator>();
|
|
// characterAttacks = GetComponent<CharacterAttacks>();
|
|
// cashCarrier = GetComponent<CashCarrier>();
|
|
// cashAI = GetComponent<CashSystemAI>();
|
|
|
|
// // Ensure this character is on enemy team
|
|
// if (teamMember != null)
|
|
// {
|
|
// teamMember.CurrentTeam = TeamMember.Team.EnemyTeam;
|
|
// }
|
|
// }
|
|
|
|
// private void OnEnable()
|
|
// {
|
|
// Debug.Log($"[EnemyAIController] Enabled on {gameObject.name}");
|
|
// StartCoroutine(AIDecisionLoop());
|
|
// }
|
|
|
|
// private void OnDisable()
|
|
// {
|
|
// Debug.Log($"[EnemyAIController] Disabled on {gameObject.name}");
|
|
// StopAllCoroutines();
|
|
// }
|
|
|
|
// private IEnumerator AIDecisionLoop()
|
|
// {
|
|
// yield return new WaitForSeconds(0.5f); // Initial delay
|
|
|
|
// while (enabled)
|
|
// {
|
|
// MakeDecision();
|
|
// yield return new WaitForSeconds(decisionInterval);
|
|
// }
|
|
// }
|
|
|
|
// private void MakeDecision()
|
|
// {
|
|
// // Lazy re-cache: CashSystemAI is added AFTER our Awake() by ConfigureCharacterControllers,
|
|
// // so the Awake-time GetComponent returns null. Re-check here once.
|
|
// if (cashAI == null) cashAI = GetComponent<CashSystemAI>();
|
|
|
|
// // If CashSystemAI is attached and active, delegate ALL decisions to it
|
|
// if (cashAI != null && cashAI.enabled)
|
|
// {
|
|
// // CashSystemAI handles the high-level decision making via its own Update()
|
|
// return;
|
|
// }
|
|
|
|
// // Standard enemy AI decision making
|
|
// TeamMember nearestEnemy = teamMember.FindNearestEnemy(); // Player team
|
|
|
|
// // Priority 1: Attack nearby player team members
|
|
// if (nearestEnemy != null)
|
|
// {
|
|
// float distanceToEnemy = Vector3.Distance(transform.position, nearestEnemy.transform.position);
|
|
|
|
// if (distanceToEnemy <= attackRange)
|
|
// {
|
|
// SetState(AIState.Attack);
|
|
// currentTarget = nearestEnemy;
|
|
// PerformAttack();
|
|
// return;
|
|
// }
|
|
// else if (distanceToEnemy <= aggroRange && aggressive)
|
|
// {
|
|
// SetState(AIState.ChaseEnemy);
|
|
// currentTarget = nearestEnemy;
|
|
// MoveToTarget(nearestEnemy.transform.position);
|
|
// return;
|
|
// }
|
|
// }
|
|
|
|
// // Priority 2: Patrol or idle
|
|
// if (aggressive && nearestEnemy != null)
|
|
// {
|
|
// float distanceToEnemy = Vector3.Distance(transform.position, nearestEnemy.transform.position);
|
|
// if (distanceToEnemy <= detectionRange)
|
|
// {
|
|
// SetState(AIState.ChaseEnemy);
|
|
// currentTarget = nearestEnemy;
|
|
// MoveToTarget(nearestEnemy.transform.position);
|
|
// return;
|
|
// }
|
|
// }
|
|
|
|
// // Default: Idle
|
|
// SetState(AIState.Idle);
|
|
// StopMovement();
|
|
// }
|
|
|
|
// private void SetState(AIState newState)
|
|
// {
|
|
// if (currentState != newState)
|
|
// {
|
|
// currentState = newState;
|
|
// Debug.Log($"[EnemyAIController] {gameObject.name} -> {newState}");
|
|
// }
|
|
// }
|
|
|
|
// private void MoveToTarget(Vector3 position)
|
|
// {
|
|
// if (navAgent != null && navAgent.isActiveAndEnabled && navAgent.isOnNavMesh)
|
|
// {
|
|
// navAgent.isStopped = false;
|
|
// navAgent.SetDestination(position);
|
|
|
|
// // Update animator
|
|
// if (animator != null)
|
|
// {
|
|
// float speed = navAgent.velocity.magnitude / navAgent.speed;
|
|
// animator.SetFloat("Speed", speed);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// private void StopMovement()
|
|
// {
|
|
// if (navAgent != null && navAgent.isActiveAndEnabled && navAgent.isOnNavMesh)
|
|
// {
|
|
// navAgent.isStopped = true;
|
|
// navAgent.velocity = Vector3.zero;
|
|
// }
|
|
|
|
// if (animator != null)
|
|
// {
|
|
// animator.SetFloat("Speed", 0f);
|
|
// }
|
|
// }
|
|
|
|
// private void PerformAttack()
|
|
// {
|
|
// if (Time.time - lastAttackTime < attackCooldown) return;
|
|
|
|
// // Face the target
|
|
// if (currentTarget != null)
|
|
// {
|
|
// Vector3 direction = (currentTarget.transform.position - transform.position).normalized;
|
|
// direction.y = 0;
|
|
// if (direction.sqrMagnitude > 0.001f)
|
|
// {
|
|
// transform.rotation = Quaternion.LookRotation(direction);
|
|
// }
|
|
// }
|
|
|
|
// // Perform attack using CharacterAttacks if available
|
|
// if (characterAttacks != null)
|
|
// {
|
|
// // Choose a random attack
|
|
// string[] attacks = { AnimationNames.Jab, AnimationNames.LowKick, AnimationNames.Haymaker };
|
|
// string randomAttack = attacks[Random.Range(0, attacks.Length)];
|
|
|
|
// characterAttacks.PunchAttacksDirectly(randomAttack);
|
|
// lastAttackTime = Time.time;
|
|
// }
|
|
// else if (animator != null)
|
|
// {
|
|
// // Fallback to direct animation trigger
|
|
// animator.SetTrigger("attack");
|
|
// lastAttackTime = Time.time;
|
|
// }
|
|
// }
|
|
|
|
// private void Update()
|
|
// {
|
|
// // When CashSystemAI is driving, don't interfere with NavMeshAgent
|
|
// if (cashAI != null && cashAI.enabled) return;
|
|
|
|
// // Continuous state updates
|
|
// switch (currentState)
|
|
// {
|
|
// case AIState.Attack:
|
|
// if (currentTarget != null)
|
|
// {
|
|
// float distance = Vector3.Distance(transform.position, currentTarget.transform.position);
|
|
// if (distance > attackRange * 1.5f)
|
|
// {
|
|
// // Move closer
|
|
// MoveToTarget(currentTarget.transform.position);
|
|
// }
|
|
// else
|
|
// {
|
|
// StopMovement();
|
|
// PerformAttack();
|
|
// }
|
|
// }
|
|
// break;
|
|
|
|
// case AIState.ChaseEnemy:
|
|
// if (currentTarget != null)
|
|
// {
|
|
// MoveToTarget(currentTarget.transform.position);
|
|
// }
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// Set a specific target for this AI to attack
|
|
// /// </summary>
|
|
// public void SetTarget(TeamMember target)
|
|
// {
|
|
// currentTarget = target;
|
|
// if (target != null)
|
|
// {
|
|
// SetState(AIState.ChaseEnemy);
|
|
// }
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// Command this AI to move to a specific position
|
|
// /// </summary>
|
|
// public void MoveTo(Vector3 position)
|
|
// {
|
|
// MoveToTarget(position);
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// Get current AI state
|
|
// /// </summary>
|
|
// public AIState GetCurrentState() => currentState;
|
|
//}
|