Newer
Older
HierarchicalFSM-Unity3D / Assets / Scripts / NPC / FSM / Actions / Combat / Ranged / GoToLocationCoverAction.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "Finite State Machine/Action/Combat/Ranged/GoToCoverLocation")]
public class GoToLocationCoverAction : Action
{
    [SerializeField] private LookAt lootAtAction;
    public override void Execute(FSM fsm)
    {
        GameObject target = fsm.Controller.AgentFOV.GetTarget();

        Debug.Log($"Execute action: {nameof(GoToLocationCoverAction)}");
        Debug.Log($"Parent State: {fsm.CurrentState().GetParentState()}");

        if (fsm.CurrentState().GetParentState() is RangedCombatState)
        {
            //Cast to the parent state that contains a reference to the the chosen cover location
            RangedCombatState state = (RangedCombatState)fsm.CurrentState().GetParentState();

            if (state.coverObject != null)
            {
                Debug.Log($"Go to cover location: {state.coverObject}");

                //Calculate the closest point of the cover spot closer to the NPC
                Vector3 closestPointOnCover = state.coverObject.GetComponent<Collider>().ClosestPoint(fsm.transform.position);

                //Check the direction from the cover to the target
                Vector3 coverToTargetDir = (target.transform.position - closestPointOnCover).normalized;

                //Check the direction from the cover to the NPC
                Vector3 coverToNPCDir = (fsm.transform.position - closestPointOnCover).normalized;

                //Calculate final target position behind cover
                float dotProduct = Vector3.Dot(coverToTargetDir, coverToNPCDir);

                //Calculate the final cover position
                Vector3 finalCoverPosition = closestPointOnCover;

                if (dotProduct > 0)
                {
                    //Calculate the normal of the cover(using the normal of the closest point on the collider)
                    RaycastHit hit;

                    if (Physics.Raycast(closestPointOnCover + Vector3.up, -coverToTargetDir, out hit))
                    {
                        finalCoverPosition = hit.point;
                    }
                }

                //Set Agent cover destionation
                Debug.Log($"Spot cover location: {fsm.Controller.Agent.destination}");
                fsm.Controller.Agent.SetDestination(finalCoverPosition);
                fsm.Controller.Agent.stoppingDistance = 0.2f;

                //While the agent goes to the cover position it looks to the player
                if (lootAtAction != null)
                {
                    if (target != null)
                    {
                        lootAtAction.SetTarget(target);
                        lootAtAction.Execute(fsm);
                    }

                    else
                    {
                        Debug.LogWarning("Missing Target!");
                    }
                }

                else
                {
                    Debug.LogError($"Missing Component: {nameof(lootAtAction)}");
                }
            }

            else
            {
                Debug.LogError($"There is no Cover Location!");
            }

        }
    }


}