using System.Collections; using System.Collections.Generic; using UnityEngine; using InfallibleCode; using UnityEngine.AI; using UnityEngine.Playables; using UnityEngine.SceneManagement; public class PatrolManager : MonoBehaviour { private static PatrolManager _instance; public static PatrolManager GetInstance() { return _instance; } [SerializeField] public List DefinedPathPatrolPoints; [SerializeField] public List NearbyRoomPatrolPoints; [SerializeField] public List HidePatrolPoints; [SerializeField] public List ClosetHideBehaviourEnemyShouldPatrol; [SerializeField] public RoomTrigger lastRoomTriggerEnemySeenPlayer; //OPEN WHEN SCRIPTS ARE MADE!!!! //[SerializeField] public List TableHideBehaviourEnemyShouldPatrol; [SerializeField] public List BedHideBehaviourEnemyShouldPatrol; public Transform takeOutFromHidingSpotPosition; public ClosetHideBehaviour closetHideBehaviourPlayerIsHiding; public BedHideBehaviourBase bedHideBehaviourPlayerIsHiding; public PlayableDirector medeasCurrentPlayableDirector; [SerializeField] public bool _canChangePoint = true; /*[SerializeField] private */ public int _destinationPoint; public bool CanPatrol; public bool CanPatrolNearbyRooms; public bool CanPatrolAroundTheHouse; //closest patrol point void Awake() { if (!_instance) { _instance = this; } } private void Update() { if (CanPatrol) { isPatroling(); //UpdatePath(); } } // I want to create a switch where i will put the rooms and every room will have its own transform points public enum Rute { DefinedPath, SearchingForHiddenPlayerPath, NearbyRoomsPath, GoesToTakeOutPlayerFromHiddingSpotPath, LostPlayerPath } public Rute content = Rute.DefinedPath; public void isPatroling() { switch (content) { case Rute.DefinedPath: Patrol(DefinedPathPatrolPoints); break; case Rute.SearchingForHiddenPlayerPath: //Goes to the room of the player to search //in the hidding spots except the players //and then leaves for nearby rooms AKA LostPlayerPath PatrolHidingSpots(); break; case Rute.NearbyRoomsPath: if (_destinationPoint > NearbyRoomPatrolPoints.Count -1) { //MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.isStopped = true; print("Should go to DefinedPath after checked all nearby rooms"); _destinationPoint = 0; content = Rute.DefinedPath; MedeaDemonicEnemyBehaviour.GetInstance().state = MedeaDemonicEnemyBehaviour.medeaState.Patroling; } PatrolNearbyRooms(NearbyRoomPatrolPoints); break; case Rute.GoesToTakeOutPlayerFromHiddingSpotPath: //Closest Patrol point to the player //Go to transform to uncover the player TakePlayerOutOfHidingSpot(); break; case Rute.LostPlayerPath: //Gets the players position and patrols in the defined //path starting from the nearest point //OPEN THIS IS YOU WANT TO DESPAWN HER 5 MIN AFTER SHE LOST THE PLAYER //MedeaDemonicEnemyBehaviour.GetInstance().StartMedeaDespawn(); break; } } IEnumerator WaitForNext() { Debug.Log("Enemy Is Waiting"); yield return new WaitForSeconds(5f); Debug.Log("Enemy can move again now"); MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.isStopped = false; _canChangePoint = true; #region Animation if (MedeaDemonicEnemyBehaviour.GetInstance().medeaAnimator.GetBool("IsLookingAround")) //If is looking around: { MedeaDemonicEnemyBehaviour.GetInstance().medeaAnimator.SetBool("IsLookingAround", false); } #endregion) //StopAllCoroutines(); } void Patrol(List point) { if (_canChangePoint) { if (!MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.pathPending && MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.remainingDistance < 0.25) { #region Play animation MedeaDemonicEnemyBehaviour.GetInstance().medeaAnimator.SetBool("IsLookingAround", true); #endregion MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.isStopped = true; MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination = point[_destinationPoint].position; _canChangePoint = false; _destinationPoint = (_destinationPoint + 1) % point.Count; StartCoroutine(WaitForNext()); } } } void PatrolNearbyRooms(List point) { if (_canChangePoint) { if (!MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.pathPending && MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.remainingDistance < 0.25) { #region Play animation MedeaDemonicEnemyBehaviour.GetInstance().medeaAnimator.SetBool("IsLookingAround", true); #endregion MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.isStopped = true; MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination = point[_destinationPoint].position; _canChangePoint = false; _destinationPoint = _destinationPoint + 1; StartCoroutine(WaitForNext()); } } } /// /// Updates Enemy's take out of hiding spot. /// void TakePlayerOutOfHidingSpot() { print("Take player out bitch"); MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination = takeOutFromHidingSpotPosition.position; CanPatrol = true; // 13.8.24 Yiannis & Maya Added if (!MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.pathPending && MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.remainingDistance < 0.5) { if (HideManager.GetInstance().InCloset) { StartCoroutine(UpdateSmoothlyPatrolHidingSpotMedeaRotation(2f, takeOutFromHidingSpotPosition)); print("Reached hiding spot destination for InCloset"); closetHideBehaviourPlayerIsHiding.PlayEnemyKillPlayerInClosetCutscene(); } else if (HideManager.GetInstance().UnderBed) { print("Reached hiding spot destination for UnderBed"); if (HideManager.GetInstance().isInBedRightSide) { StartCoroutine(UpdateSmoothlyPatrolHidingSpotMedeaRotation(2f, takeOutFromHidingSpotPosition)); bedHideBehaviourPlayerIsHiding.PlayEnemyBedSearchCutscene(); } else { StartCoroutine(UpdateSmoothlyPatrolHidingSpotMedeaRotation(2f, takeOutFromHidingSpotPosition)); bedHideBehaviourPlayerIsHiding.PlayEnemyBedSearchCutscene(); } } else if (HideManager.GetInstance().UnderTable) { print("Reached hiding spot destination for UnderTable"); //Play necessary kill cutscene. } CanPatrol = false; _canChangePoint = false; } } public void UpdatePatrolHidingSpots() { ClosetHideBehaviourEnemyShouldPatrol.Clear(); BedHideBehaviourEnemyShouldPatrol.Clear(); HidePatrolPoints.Clear(); print("Update patrol hiding spots"); foreach (var closetHideBehaviour in RoomManager.GetInstance().closetHideBehaviour) { if (!closetHideBehaviour.playerIsHidingInThisCloset) { ClosetHideBehaviourEnemyShouldPatrol.Add(closetHideBehaviour); HidePatrolPoints.Add(closetHideBehaviour.enemySearchPosition); } else //If player is hiding in this closet: { //if (HideManager.GetInstance().InCloset) //{ if (closetHideBehaviour.lightSwitch != null) { HideManager.GetInstance().currentClosetLightSwitch = closetHideBehaviour.lightSwitch; } else { HideManager.GetInstance().currentClosetLightSwitch = null; } //} } } foreach (var bedHideBehaviour in RoomManager.GetInstance().bedHideBehaviour) { if (!bedHideBehaviour.playerIsHidingUnderBed) { if (bedHideBehaviour.isInRightSide) { BedHideBehaviourEnemyShouldPatrol.Add(bedHideBehaviour); HidePatrolPoints.Add(bedHideBehaviour.enemySearchPositionRight); print("Added BedHideBehaviourEnemyShouldPatrol RIGHT SIDE"); } else { BedHideBehaviourEnemyShouldPatrol.Add(bedHideBehaviour); HidePatrolPoints.Add(bedHideBehaviour.enemySearchPositionLeft); print("Added BedHideBehaviourEnemyShouldPatrol LEFT SIDE"); } } } } private void UpdatePatrolHidingSpotMedeaRotation() { if (_destinationPoint - 1 != -1) { //Vector3 dir = HidePatrolPoints[_destinationPoint - 1].position - MedeaDemonicEnemyBehaviour.GetInstance()._medea.position; //dir.y = 0; // This allows the object to only rotate on its y axis //Quaternion rot = Quaternion.LookRotation(dir.normalized, Vector3.up); // Use dir.normalized to ensure proper alignment //float rotationSpeed = 2f; //// Set Y rotation separately //rot = Quaternion.Euler(0, rot.eulerAngles.y, 0); // Keep only the Y rotation //MedeaDemonicEnemyBehaviour.GetInstance()._medea.localRotation = Quaternion.Lerp(MedeaDemonicEnemyBehaviour.GetInstance()._medea.localRotation, rot, rotationSpeed * Time.deltaTime); // Get the direction to the destination Vector3 direction = (MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination - transform.position).normalized; // Calculate the rotation to face the destination Quaternion lookRotation = Quaternion.LookRotation(MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination); // Apply the rotation to the agent MedeaDemonicEnemyBehaviour.GetInstance()._medea.rotation = HidePatrolPoints[_destinationPoint - 1].rotation; } } IEnumerator UpdateSmoothlyPatrolHidingSpotMedeaRotation(float rotationSpeed, Transform targetDestination) { float timeElapsed = 0; float lerpDuration = 1/ rotationSpeed; while (timeElapsed < lerpDuration) { // Calculate the target rotation based on the current destination point Quaternion targetRotation = targetDestination.rotation; // Smoothly interpolate between the current rotation and the target rotation MedeaDemonicEnemyBehaviour.GetInstance()._medea.transform.rotation = Quaternion.Slerp(MedeaDemonicEnemyBehaviour.GetInstance()._medea.transform.rotation, targetRotation, timeElapsed / lerpDuration); timeElapsed += Time.deltaTime; yield return null; } } void PatrolHidingSpots(/*List point*/) { //_destinationPoint = 0; //UpdatePatrolHidingSpotMedeaRotation(); if (_canChangePoint) { #region Check if needed //if (ClosetHideBehaviourEnemyShouldPatrol != null) //{ // MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination = ClosetHideBehaviourEnemyShouldPatrol[_destinationPoint].enemySearchPosition.position; //} ////else if (TableHideBehaviourEnemyShouldPatrol) ////{ ////} ////else if (BedHideBehaviourEnemyShouldPatrol) ////{ ////} /// #endregion if (_destinationPoint < HidePatrolPoints.Count) { MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.destination = HidePatrolPoints[_destinationPoint].position; if (!MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.pathPending && MedeaDemonicEnemyBehaviour.GetInstance()._medeaAI.remainingDistance < 0.1) { #region Check if needed //if (ClosetHideBehaviourEnemyShouldPatrol != null) //{ // foreach (var closetHideBehaviourEnemyShouldPatrol in ClosetHideBehaviourEnemyShouldPatrol) // { // ClosetHideBehaviourEnemyShouldPatrol[_destinationPoint].PlayEnemyClosetSearchCutscene(); // } //} ////else if (TableHideBehaviourEnemyShouldPatrol) ////{ ////} ////else if (BedHideBehaviourEnemyShouldPatrol) ////{ ////} /// #endregion StartCoroutine(UpdateSmoothlyPatrolHidingSpotMedeaRotation(2f, HidePatrolPoints[_destinationPoint])); print("Play Enemy Closet Search Cutscene!"); #region Closet HidePatrolPoints[_destinationPoint].parent.transform.parent.TryGetComponent(out ClosetHideBehaviour _closetHideBehaviour); if (_closetHideBehaviour != null) { _closetHideBehaviour.PlayEnemyClosetSearchCutscene(); } #endregion #region Bed HidePatrolPoints[_destinationPoint].parent.transform.parent.transform.parent.TryGetComponent(out BedHideBehaviourBase _bedHideBehaviour); if (_bedHideBehaviour != null) { _bedHideBehaviour.PlayEnemyBedSearchCutscene(); } #endregion _destinationPoint = _destinationPoint +1; _canChangePoint = false; } } else { _destinationPoint = 0; content = Rute.NearbyRoomsPath; } } if (HideManager.GetInstance().currentClosetLightSwitch != null && HideManager.GetInstance().InCloset && RoomManager.GetInstance().LastRoomTriggerPlayerEntered.enemyAIIsInTrigger && HideManager.GetInstance().lightSwitchTimerIsRunning == false) { HideManager.GetInstance().StartClosetCoroutineTimer(); // MedeaDemonicEnemyBehaviour.GetInstance().state = MedeaDemonicEnemyBehaviour.medeaState.TakingOutPlayerFromHiddingSpot; } } public void UpdateTakeOutPlayerSpot() { if (HideManager.GetInstance().InCloset) { foreach (var _closetHideBehaviour in RoomManager.GetInstance().closetHideBehaviour) { if (_closetHideBehaviour.playerIsHidingInThisCloset) { closetHideBehaviourPlayerIsHiding = _closetHideBehaviour; takeOutFromHidingSpotPosition = _closetHideBehaviour.enemySearchPosition; } } } else if (HideManager.GetInstance().UnderBed) { foreach (var _bedHideBehaviour in RoomManager.GetInstance().bedHideBehaviour) { if (_bedHideBehaviour.playerIsHidingUnderBed) { bedHideBehaviourPlayerIsHiding = _bedHideBehaviour; if (_bedHideBehaviour.isInRightSide) { takeOutFromHidingSpotPosition = _bedHideBehaviour.enemySearchPositionRight; } else { takeOutFromHidingSpotPosition = _bedHideBehaviour.enemySearchPositionLeft; } } } //Implementation for bed. } else if (HideManager.GetInstance().UnderTable) { //Implementation for table. } } public void SetNearbyRoomsPatrolPoints() { NearbyRoomPatrolPoints.Clear(); lastRoomTriggerEnemySeenPlayer = RoomManager.GetInstance().LastRoomTriggerPlayerEntered; if (lastRoomTriggerEnemySeenPlayer == null) { Debug.LogWarning("LastRoomTriggerPlayerEntered is null. Cannot set nearby room patrol points."); return; } // Use _nearbyRoomSceneNames from RoomManager foreach (string nearbySceneName in RoomManager.GetInstance()._nearbyRoomSceneNames) { List patrolPoints = GetPatrolPointsForScene(nearbySceneName); if (patrolPoints != null) { NearbyRoomPatrolPoints.AddRange(patrolPoints); } } Debug.Log($"Nearby patrol points set. Found {NearbyRoomPatrolPoints.Count} patrol points."); } public List GetNearbySceneNames() { List nearbyScenes = new List(); // Add manually defined nearby scenes foreach (string sceneName in RoomManager.GetInstance()._nearbyRoomSceneNames) // Assume nearbyRoomSceneNames is a string list { nearbyScenes.Add(sceneName); } return nearbyScenes; } public List GetPatrolPointsForScene(string sceneName) { List patrolPoints = new List(); if (!DynamicSceneManager.GetInstance().IsSceneLoaded(sceneName)) { Debug.LogWarning($"Scene {sceneName} is not loaded. Cannot retrieve patrol points."); return patrolPoints; } // Find RoomTriggers in the scene and collect their patrol points Scene scene = SceneManager.GetSceneByName(sceneName); foreach (GameObject rootObject in scene.GetRootGameObjects()) { RoomTrigger roomTrigger = rootObject.GetComponentInChildren(); if (roomTrigger != null) { patrolPoints.AddRange(roomTrigger.GetPatrolPoints()); } } return patrolPoints; } //public void SetNearbyRoomsPatrolPoints() //{ // NearbyRoomPatrolPoints.Clear(); // lastRoomTriggerEnemySeenPlayer = RoomManager.GetInstance().LastRoomTriggerPlayerEntered; // foreach (RoomTrigger nearbyRoomTrigger in lastRoomTriggerEnemySeenPlayer.nearbyRoomTriggers) // { // NearbyRoomPatrolPoints.Add(nearbyRoomTrigger.transform); // } //} //Transform CalculateHiddingSpotPatrolPoint() //{ // if (MedeaDemonicEnemyBehaviour.GetInstance().IsPlayerHidden()) // { // List playersHiddingSpots = RoomManager.GetInstance()._roomHiddingSpots; // Transform closestSpot = null; // float closestDistance = Mathf.Infinity; // foreach (Transform spot in playersHiddingSpots) // { // float distance = Vector3.Distance(PlayerManager.GetInstance().transform.position, spot.position); // if (distance < closestDistance) // { // closestDistance = distance; // closestSpot = spot; // } // } // return closestSpot; // } // return null; //} }