Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / NPC / Orc / Actions / MeleeAttackAction.cs
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;
    }
}