190 lines
4.8 KiB
C#
190 lines
4.8 KiB
C#
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;
|
|
|
|
int buttonIndex = i;
|
|
UnityAction action = () => OnButtonPressed(buttonIndex);
|
|
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
|
|
}
|