using UnityEngine; using System.Collections; using MyCollections.AI.FinitStateMachine; [CreateAssetMenu(menuName = "Finite State Machine/Action/MeleeAttackAction")] public class MeleeAttackAction : Action { [Header("Melee Combat Settings:")] [SerializeField] private float attackRange; [SerializeField] private LayerMask targetLayerMask; [SerializeField] private float attackBaseValue = 5f; [SerializeField] private float attackTimer = 2f; public override void Run(FSM fsm) { // Start the attack coroutine if not already running NPCConroller controller = fsm.Controller; if (controller != null && !controller.IsCoroutineRunning) { controller.StartCoroutine(RunAttack(fsm, attackTimer)); } } private void ApplyAttack(FSM fsm) { OrcNPCController controller = fsm.Controller as OrcNPCController; if (controller == null) { Debug.LogWarning("MeleeAttackAction: Controller is not an OrcNPCController."); return; } Animator anim = controller.Animator; GameObject weapon = controller.Weapon; if (controller.AgentFOV.GetTarget() == null || anim == null || weapon == null) { Debug.LogWarning("MeleeAttackAction: Missing required components."); return; } if (!controller.isAttacking) { weapon.SetActive(true); Vector2 origin = controller.transform.position; Vector2 direction = ((Vector2)controller.AgentFOV.GetTarget().transform.position - origin).normalized; RaycastHit2D hit = Physics2D.Raycast(origin, direction, attackRange, targetLayerMask); Debug.DrawRay(origin, direction * attackRange, Color.red, 1.5f); controller.isAttacking = true; if (hit.collider != null && hit.collider.TryGetComponent(out IHealthSystem healthSystem)) { Debug.Log($"Apply Damage to the {hit.collider.gameObject}!"); healthSystem.TakeDamage(attackBaseValue); } } } private IEnumerator RunAttack(FSM fsm, float wait) { NPCConroller controller = fsm.Controller; if (controller == null) yield break; controller.IsCoroutineRunning = true; // Ensure the coroutine runs only while the FSM is in the current state while (fsm.CurrentState() == fsm.CurrentState()) { yield return new WaitForSeconds(wait); ApplyAttack(fsm); } controller.IsCoroutineRunning = false; } }