using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; [CreateAssetMenu(menuName = "Finite State Machine/Condition/TryToFindCoverLocation")] public class TryToFindCoverLocation : Condition { [SerializeField] private CheckTargetState targetState; [SerializeField] private string tag; //Target object tab [SerializeField] private ushort numberOftries = 3; //Number of try checks to find a cover location public override bool CheckCondition(FSM fsm) { Debug.Log("CheckCondition"); //Checks if the target is on specific state if (targetState.CheckCondition(fsm)) { Debug.Log($"Find Spot: {FindSpot(fsm)}"); if (FindSpot(fsm) != null) { RangedCombatState state = (RangedCombatState)fsm.CurrentState().GetParentState(); if (state != null) { if (state is RangedCombatState) { state.coverObject = FindSpot(fsm); return true; } return false; } return false; } return false; } else return false; } //tris to find a cover location for the NPC private GameObject FindSpot(FSM fsm) { Awareness agentAware = fsm.Controller.AgentAwareness; GameObject target = fsm.Controller.AgentFOV.GetTarget(); if (agentAware != null && target != null) { //Use the sensor agentAware.SetTargetTag(tag); agentAware.Enable = true; if (agentAware.TargetsList.Count > 0) { //Closest target float closestTargetDistance = float.MaxValue; GameObject coverObj = null; foreach (GameObject g in agentAware.TargetsList) { float distance = Vector3.Distance(fsm.transform.position, g.transform.position); if (distance < closestTargetDistance || distance <= 0f) { if (IsSpotProtected(target.transform, g.transform)) { coverObj = g; closestTargetDistance = distance; } } } return coverObj; } return null; } return null; } //If there are any available spots check if the spot protects from the player private bool IsSpotProtected(Transform target, Transform coverObject) { RaycastHit hit; //Checks if either target or cover object is not null if (target != null && coverObject != null) { //Calculates the direction Vector3 directionToPlayer = (target.position - coverObject.position).normalized; //Performs the raycast to check if the cover object will provide actual cover to the NPC if (Physics.Raycast(coverObject.position, directionToPlayer, out hit)) { return hit.transform != target; } Debug.LogWarning($"Raycast failed for cover check."); return false; } else { Debug.LogWarning($"Missing: {nameof(target)} or {nameof(coverObject)}"); return false; } } }