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!"); } } } }