using System.Collections.Generic; using System.Linq; using EscapeRoomEngine.Engine.Runtime.Modules; using EscapeRoomEngine.Engine.Runtime.Modules.State; using EscapeRoomEngine.Engine.Runtime.Utilities; using JetBrains.Annotations; using NaughtyAttributes; using UnityEngine; using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger; using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType; namespace Station46.Runtime.Puzzle_A { /// /// The main component for the terminal module. /// [RequireComponent(typeof(Animator))] public class Terminal : CyclicStepPuzzle { private static readonly int LightFlash = Animator.StringToHash("Light Flash"); [BoxGroup("Internal")] [Required] public Emission terminalLight; [BoxGroup("Internal")] [ValidateInput("SymbolCount", "Must have same amount of symbols and slots.")] public List symbols; [BoxGroup("Internal")] public List symbolSlots; private IOption _activeSymbol; private Animator _animator; private Ball _ball; private void Awake() { _animator = GetComponent(); List symbolInstances = new(symbols.Count); symbolInstances.AddRange(symbols.Select((t, i) => Instantiate(t, symbolSlots[i], false))); symbols = symbolInstances; } protected override void Start() { base.Start(); PuzzleEvent += (_, type) => { // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault switch (type) { case PuzzleEventType.Restarted: _ball.Active = true; terminalLight.color = EscapeRoomEngine.Engine.Runtime.Engine.Theme.puzzleColor.hdr; symbols.ForEach(symbol => symbol.Enable()); break; case PuzzleEventType.Solved: _ball.Active = false; terminalLight.color = EscapeRoomEngine.Engine.Runtime.Engine.Theme.solvedColor.hdr; symbols.ForEach(symbol => symbol.Disable()); break; case PuzzleEventType.WrongInput: _animator.SetTrigger(LightFlash); break; } }; symbols.ForEach(symbol => { symbol.ButtonEvent += (_, type) => { if (type == ButtonEventType.Pressed) { PressedSymbol(symbol.symbolNumber); } }; }); _ball.ring.symbols.ForEach(symbol => { symbol.SymbolEvent += type => _activeSymbol = type == SymbolEventType.Activated ? Some.Of(symbol) : None.New(); }); } public override void SetModule(Module module) { base.SetModule(module); // The terminal requires a related symbol ball module var firstRelatedModule = Module.relatedModules[0]; if (firstRelatedModule.State is Ball ball) { _ball = ball; } else { throw new EngineException("Terminal was not assigned a related Ball."); } TurnOnLights(); } [UsedImplicitly] // required in animation internal void TurnOnLights() { terminalLight.active = true; _ball.StatusLight = true; } [UsedImplicitly] // required in animation internal void TurnOffLights() { terminalLight.active = false; _ball.StatusLight = false; } private void PressedSymbol(int number) { if (!Solved) { Logger.Log($"Pressed symbol {number} on {this}", LogType.PuzzleDetail); _activeSymbol.Match(some: symbol => { if (number == symbol.symbolNumber) { CheckStep(symbol.symbolPosition); } else { WrongInput(); } }, none: WrongInput); } } #region Debug Buttons [UsedImplicitly] [Button(enabledMode: EButtonEnableMode.Playmode)] public void PressSymbol0() => PressedSymbol(0); [UsedImplicitly] [Button(enabledMode: EButtonEnableMode.Playmode)] public void PressSymbol1() => PressedSymbol(1); [UsedImplicitly] [Button(enabledMode: EButtonEnableMode.Playmode)] public void PressSymbol2() => PressedSymbol(2); #endregion [UsedImplicitly] // used for field validation private bool SymbolCount(List list) => list.Count == symbolSlots.Count; } }