using System; using System.Collections.Generic; using EscapeRoomEngine.Engine.Runtime.Modules.State; using EscapeRoomEngine.Engine.Runtime.Utilities; using JetBrains.Annotations; using NaughtyAttributes; using Station46.Modules.Hover_Sphere.Scripts; using Station46.Modules.Symbols.Scripts; using Station46.Scripts; using UnityEngine; namespace Station46.Modules.Hexagon.Scripts { [Serializable] internal struct ButtonAction { public SymbolButton button; public List stateIndices; } /// /// The main component for the hexagon module. /// public class Hexagon : StatePuzzle { [Tooltip("How many seconds the buttons should be disabled until another input is accepted.")] [SerializeField] [Min(0)] private float buttonCooldown; [ValidateInput("CorrectRotatorCount")] public List rotators; [InfoBox("Every button action will toggle the states at the given indices between 0 and 90 degrees.")] [SerializeField] private List buttonActions; [BoxGroup("Internal")] [SerializeField] private List lights; [BoxGroup("Internal")] [SerializeField] private Crystal crystal; private float _previousPress = -1; protected override void Start() { base.Start(); PuzzleEvent += (_, type) => { // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault switch (type) { case PuzzleEventType.Restarted: var color = EscapeRoomEngine.Engine.Runtime.Engine.Theme.puzzleColor; crystal.Color = color; lights.ForEach(emission => emission.color = color.hdr); rotators.ForEach(rotator => rotator.Emission.color = color.hdr); buttonActions.ForEach(action => action.button.Enable()); break; case PuzzleEventType.Solved: color = EscapeRoomEngine.Engine.Runtime.Engine.Theme.solvedColor; crystal.Color = color; lights.ForEach(emission => emission.color = color.hdr); rotators.ForEach(rotator => rotator.Emission.color = color.hdr); buttonActions.ForEach(action => action.button.Disable()); break; } }; foreach (var buttonAction in buttonActions) { buttonAction.button.ButtonEvent += (_, type) => { if (type == ButtonEventType.Pressed && _previousPress + buttonCooldown <= Time.time) { Switch(buttonAction); _previousPress = Time.time; } }; } crystal.Active = true; lights.ForEach(emission => emission.active = true); rotators.ForEach(rotator => rotator.Emission.active = true); } protected override void SetState(int index, int value, bool checkSolution) { base.SetState(index, value, checkSolution); for (var i = 0; i < stateCount; i++) { rotators[i].angle = states[i]; } } /// /// Switch all rotators specified by a given action. /// private void Switch(ButtonAction action) { for (var i = 0; i < action.stateIndices.Count; i++) { var stateIndex = action.stateIndices[i]; var current = OrientationExtensions.FromAngle(states[stateIndex]); current = current == Orientation.North ? current.Rotated(1) : current.Rotated(-1); // set state but only check solution on the last change SetState(stateIndex, current.AngleInt(), i == action.stateIndices.Count - 1); } } [UsedImplicitly] // used for field validation private bool CorrectRotatorCount(List list) => list != null && list.Count == stateCount; } }