using System; using System.Collections.Generic; using EscapeRoomEngine.Engine.Runtime; using EscapeRoomEngine.Engine.Runtime.Modules; using EscapeRoomEngine.Engine.Runtime.Utilities; using JetBrains.Annotations; using NaughtyAttributes; using UnityEngine; namespace EscapeRoomEngine.Desert.Runtime.Puzzle_B { [Serializable] internal struct ButtonAction { public SymbolButton button; public List stateIndices; } public class PuzzleB : StatePuzzle { [SerializeField] [Min(0)] private float buttonCooldown = 1; [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 DynamicColor _puzzleColor, _solvedColor; private float _previousPress = -1; protected override void Awake() { base.Awake(); _puzzleColor = Engine.Runtime.Engine.DefaultEngine.theme.puzzleColor; _solvedColor = Engine.Runtime.Engine.DefaultEngine.theme.solvedColor; } protected override void Start() { base.Start(); PuzzleEvent += (_, type) => { switch (type) { case PuzzleEventType.Restarted: crystal.Color = _puzzleColor; lights.ForEach(emission => emission.color = _puzzleColor.hdr); rotators.ForEach(rotator => rotator.Emission.color = _puzzleColor.hdr); buttonActions.ForEach(action => action.button.Enable()); break; case PuzzleEventType.Solved: crystal.Color = _solvedColor; lights.ForEach(emission => emission.color = _solvedColor.hdr); rotators.ForEach(rotator => rotator.Emission.color = _solvedColor.hdr); buttonActions.ForEach(action => action.button.Disable()); break; case PuzzleEventType.WrongInput: break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } }; 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]; } } 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] private bool CorrectRotatorCount(List list) => list != null && list.Count == stateCount; } }