using System; using UnityEngine; using UnityEngine.Events; public class ButtonSequenceDoorPuzzle : MonoBehaviour { [Header("References")] [Tooltip("All available buttons for this puzzle.")] [SerializeField] private WallInteractButton[] buttons; [Tooltip("Door to open when the sequence is correct.")] [SerializeField] private SlidingDoor targetDoor; [Tooltip("Optional blocks controlled by this puzzle (reset with SetOff on start/wrong input).")] [SerializeField] private TestBlock[] puzzleBlocks; [Header("Sequence")] [Tooltip("Button indices (from the buttons array) that must be pressed in order. Example: 2,0,3")] [SerializeField] private int[] requiredSequence = { 0, 1, 2 }; [Tooltip("If true, wrong input resets progress back to 0.")] [SerializeField] private bool resetOnWrongPress = true; [Tooltip("If true, puzzle can only be solved once.")] [SerializeField] private bool lockAfterSolved = true; [Header("Debug")] [SerializeField] private bool enableDebugLogs = true; private int m_progress; private bool m_isSolved; private UnityAction[] m_cachedListeners; private void OnEnable() { SetAllBlocksOff(); RegisterAllButtons(); } private void OnDisable() { UnregisterAllButtons(); } private void RegisterAllButtons() { if (buttons == null) return; m_cachedListeners = new UnityAction[buttons.Length]; for (int i = 0; i < buttons.Length; i++) { WallInteractButton button = buttons[i]; if (button == null) continue; UnityAction action = () => OnButtonPressed(i); m_cachedListeners[i] = action; button.OnInteract.AddListener(action); } } private void UnregisterAllButtons() { if (buttons == null) return; for (int i = 0; i < buttons.Length; i++) { WallInteractButton button = buttons[i]; if (button == null) continue; if (m_cachedListeners != null && i < m_cachedListeners.Length && m_cachedListeners[i] != null) button.OnInteract.RemoveListener(m_cachedListeners[i]); } m_cachedListeners = null; m_progress = 0; } private void OnButtonPressed(int buttonIndex) { Log($"Button pressed: index {buttonIndex}"); if (m_isSolved && lockAfterSolved) { Log("Puzzle already solved and locked."); return; } if (!IsSequenceValid()) { Log("Invalid sequence configuration."); return; } int expectedIndex = requiredSequence[m_progress]; Log($"Expected button index: {expectedIndex} (step {m_progress + 1}/{requiredSequence.Length})"); if (buttonIndex == expectedIndex) { m_progress++; Log($"Correct input. Progress: {m_progress}/{requiredSequence.Length}"); if (m_progress >= requiredSequence.Length) { SolvePuzzle(); } return; } if (resetOnWrongPress) { Log("Wrong input. Resetting sequence and turning puzzle blocks OFF."); m_progress = 0; SetAllBlocksOff(); return; } Log("Wrong input, but resetOnWrongPress is disabled."); } private bool IsSequenceValid() { if (requiredSequence == null || requiredSequence.Length == 0) return false; if (buttons == null || buttons.Length == 0) return false; for (int i = 0; i < requiredSequence.Length; i++) { int index = requiredSequence[i]; if (index < 0 || index >= buttons.Length) return false; } return true; } private void SolvePuzzle() { m_isSolved = true; m_progress = 0; Log("Sequence completed. Opening door."); if (targetDoor != null) targetDoor.Open(); } private void SetAllBlocksOff() { if (puzzleBlocks == null) return; for (int i = 0; i < puzzleBlocks.Length; i++) { if (puzzleBlocks[i] == null) continue; puzzleBlocks[i].SetOff(); } } private void Log(string message) { if (!enableDebugLogs) return; Debug.Log($"[{nameof(ButtonSequenceDoorPuzzle)}] {message}", this); } #if UNITY_EDITOR private void OnValidate() { if (requiredSequence == null) return; for (int i = 0; i < requiredSequence.Length; i++) { requiredSequence[i] = Math.Max(0, requiredSequence[i]); } } #endif }