using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Events; using Cinemachine; using System; namespace InfallibleCode { [Serializable] public class LockDigitsEvents { public bool ShouldCheckCurrentDigits; [Header("Correct")] public UnityEvent onDigit0Correct, onDigit1Correct, onDigit2Correct, onDigit3Correct; [Header("Incorrect")] public UnityEvent onDigit0Incorrect, onDigit1Incorrect, onDigit2Incorrect, onDigit3Incorrect; } public class Lock : MonoBehaviour, IInteractable { [SerializeField] private int[] currentDigits; // Array to hold the current digit values [SerializeField] private GameObject[] currentDigitsModel; [SerializeField] private LockWheelRotation[] currentWheel; [SerializeField] private Animator padLockAnimator; [SerializeField] private AnimateMaterialExposure[] animateWheelMaterialExposure; public float rotationSpeed = 20.0f; // Rotation speed in degrees per second public float xRotationIncrement = 35f; Vector3 currentRotation; public Vector3 targetRotation; public float targetXRotation; public bool canScrollWheel = true; private int selectedScrollIndex; // Index of the currently selected digit private int previousScrollIndex; // Index of the previous selected digit private bool isVerticalNavigationAllowed; // Flag to indicate whether vertical navigation is allowed private bool isInteractingWithLock; private bool isScrolling; bool digitMismatchFound = true; public bool isCorrectCombination; [SerializeField] private int[] correctCombination; private float cinemachineBrainCameraDefaultBlend; [SerializeField] private CinemachineVirtualCamera padlockUpCloseCMCamera; private CinemachineVirtualCamera highestPriorityCamera; public UnityEvent eventToFireAfterUnlock; public LockDigitsEvents lockDigitsEvents; private bool[] previouslyCorrectDigits; private void Start() { currentDigits = new int[4]; previouslyCorrectDigits = new bool[4]; // Αρχικοποίηση του πίνακα targetXRotation = currentDigitsModel[selectedScrollIndex].transform.localEulerAngles.x; //cinemachineBrainCameraDefaultBlend = PlayersManager.GetInstance().playerCinemachineBrain.m_DefaultBlend.m_Time; } public void Interact() { selectedScrollIndex = 0; //PlayersManager.GetInstance().playerCinemachineBrain.m_DefaultBlend.m_Time = 0; FindHighestPriorityCamera(); padlockUpCloseCMCamera.Priority = highestPriorityCamera.Priority + 1; currentWheel[selectedScrollIndex].wheelAnimator.SetBool("IsHighlighted", true); #region Player Related Logic PlayerManager.GetInstance().PlayerMovementCannotBeEnabled(); PlayerManager.GetInstance().DisablePlayerMovement(); PlayerManager.GetInstance().DisablePlayerCameraMovement(); #endregion isInteractingWithLock = true; //StartCoroutine(UpdateLock()); } void Update() { if (isInteractingWithLock) { for (int i = 0; i < animateWheelMaterialExposure.Length; i++) { animateWheelMaterialExposure[i].AnimateMaterialUpdate(); } // Handle horizontal navigation #region Horizontal navigation if (Input.GetKeyDown(KeyCode.D)) { previousScrollIndex = selectedScrollIndex; selectedScrollIndex += 1; if (selectedScrollIndex < 0) { selectedScrollIndex = 3; } else if (selectedScrollIndex > 3) { selectedScrollIndex = 0; } currentWheel[previousScrollIndex].wheelAnimator.SetBool("IsHighlighted", false); currentWheel[selectedScrollIndex].wheelAnimator.SetBool("IsHighlighted", true); } else if (Input.GetKeyDown(KeyCode.A)) { previousScrollIndex = selectedScrollIndex; selectedScrollIndex -= 1; if (selectedScrollIndex < 0) { selectedScrollIndex = 3; } else if (selectedScrollIndex > 3) { selectedScrollIndex = 0; } currentWheel[previousScrollIndex].wheelAnimator.SetBool("IsHighlighted", false); currentWheel[selectedScrollIndex].wheelAnimator.SetBool("IsHighlighted", true); } #endregion // Handle vertical navigation #region Vertical navigation if (Input.GetKeyDown(KeyCode.S) && canScrollWheel) { isScrolling = true; currentDigits[selectedScrollIndex] += 1; if (currentDigits[selectedScrollIndex] < 0) { currentDigits[selectedScrollIndex] = 9; } if (currentDigits[selectedScrollIndex] > 9) { currentDigits[selectedScrollIndex] = 0; } canScrollWheel = false; currentWheel[selectedScrollIndex].RotateWheel(true); } else if (Input.GetKeyDown(KeyCode.W) && canScrollWheel) { isScrolling = true; currentDigits[selectedScrollIndex] -= 1; if (currentDigits[selectedScrollIndex] < 0) { currentDigits[selectedScrollIndex] = 9; } if (currentDigits[selectedScrollIndex] > 9) { currentDigits[selectedScrollIndex] = 0; } canScrollWheel = false; currentWheel[selectedScrollIndex].RotateWheel(false); } else { isScrolling = false; } #endregion if (Input.GetKeyDown(KeyCode.Mouse1)) { currentWheel[selectedScrollIndex].wheelAnimator.SetBool("IsHighlighted", false); ExitLock(); } CheckCombination(); } } private void ExitLock() { isInteractingWithLock = false; //WorldInteractionManager.GetInstance().IsInteracting = false; StartCoroutine(UnblockAbilityToRewindTime()); StartCoroutine(ResetCamera()); //PlayersManager.GetInstance()._PlayerThirdPersonCamera.AddCameraLayerCullingMask(10/*Interactable UI*/); //PlayersManager.GetInstance().EnablePlayerController(); //PlayersManager.GetInstance()._PlayerThirdPersonCamera.EnableCameraMovement(); #region Player Related PlayerManager.GetInstance().PlayerMovementCanBeEnabled(); PlayerManager.GetInstance().EnablePlayerMovement(); PlayerManager.GetInstance().EnablePlayerCameraMovement(); #endregion } IEnumerator UnblockAbilityToRewindTime() { yield return new WaitForSeconds(0.1f); //ReverseTimeManager.GetInstance().BlockAbilityToPressRewindKey = false; } IEnumerator ResetCamera() { yield return new WaitForSeconds(0.1f); //PlayersManager.GetInstance().playerCinemachineBrain.m_DefaultBlend.m_Time = cinemachineBrainCameraDefaultBlend; padlockUpCloseCMCamera.Priority = 0; } private void CheckCombination() { digitMismatchFound = false; if (Input.GetKeyDown(KeyCode.E)) { for (int i = 0; i < currentDigits.Length; i++) { if (currentDigits[i] != correctCombination[i]) { digitMismatchFound = true; break; } } if (!digitMismatchFound && currentDigits.SequenceEqual(correctCombination)) { // The lock is unlocked Debug.Log("Correct combination entered, lock is unlocked!"); isCorrectCombination = true; StartCoroutine(CorrectCombination()); } else { // The lock is still locked Debug.Log("Incorrect combination entered, please try again."); StartCoroutine(PlayIncorrectCombinationAnimation()); isCorrectCombination = false; } } // **ΝΕΟΣ ΕΛΕΓΧΟΣ** για τα επιμέρους ψηφία if (lockDigitsEvents.ShouldCheckCurrentDigits) { for (int i = 0; i < currentDigits.Length; i++) { bool isDigitCorrect = currentDigits[i] == correctCombination[i]; // Αν το ψηφίο ήταν λάθος πριν και τώρα είναι σωστό if (isDigitCorrect && !previouslyCorrectDigits[i]) { TriggerCorrectEvent(i); } // Αν το ψηφίο ήταν σωστό πριν και τώρα είναι λάθος else if (!isDigitCorrect && previouslyCorrectDigits[i]) { TriggerIncorrectEvent(i); } previouslyCorrectDigits[i] = isDigitCorrect; // Ενημέρωση της προηγούμενης κατάστασης } } } private void TriggerCorrectEvent(int digitIndex) { switch (digitIndex) { case 0: lockDigitsEvents.onDigit0Correct.Invoke(); break; case 1: lockDigitsEvents.onDigit1Correct.Invoke(); break; case 2: lockDigitsEvents.onDigit2Correct.Invoke(); break; case 3: lockDigitsEvents.onDigit3Correct.Invoke(); break; } } private void TriggerIncorrectEvent(int digitIndex) { switch (digitIndex) { case 0: lockDigitsEvents.onDigit0Incorrect.Invoke(); break; case 1: lockDigitsEvents.onDigit1Incorrect.Invoke(); break; case 2: lockDigitsEvents.onDigit2Incorrect.Invoke(); break; case 3: lockDigitsEvents.onDigit3Incorrect.Invoke(); break; } } IEnumerator PlayIncorrectCombinationAnimation() { padLockAnimator.SetBool("CheckCombination", true); padLockAnimator.SetBool("CombinationWrong", true); yield return new WaitForSeconds(0.3f); padLockAnimator.SetBool("CheckCombination", false); padLockAnimator.SetBool("CombinationWrong", false); } IEnumerator CorrectCombination() { isInteractingWithLock = false; padLockAnimator.SetBool("CheckCombination", true); padLockAnimator.SetBool("CombinationCorrect", true); yield return new WaitForSeconds(0.55f); ExitLock(); yield return new WaitForSeconds(0.1f); eventToFireAfterUnlock.Invoke(); } private void FindHighestPriorityCamera() { // Get all CinemachineVirtualCamera objects in the scene CinemachineVirtualCamera[] cameras = FindObjectsOfType(); // Initialize the highest priority camera to null highestPriorityCamera = null; // Initialize the highest priority to the minimum possible value int highestPriority = int.MinValue; // Loop over all cameras and find the one with the highest priority foreach (CinemachineVirtualCamera camera in cameras) { if (camera.Priority > highestPriority) { highestPriorityCamera = camera; highestPriority = camera.Priority; } } } } }