Files
modular-vr/Assets/Station46/Modules/Hexagon/Scripts/Hexagon.cs
2023-03-22 17:03:55 +01:00

112 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Modules.State;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using JetBrains.Annotations;
using NaughtyAttributes;
using Station46.Runtime.Puzzle_A;
using UnityEngine;
namespace Station46.Runtime.Puzzle_B
{
[Serializable]
internal struct ButtonAction
{
public SymbolButton button;
public List<int> stateIndices;
}
/// <summary>
/// The main component for the hexagon module.
/// </summary>
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<Rotator> rotators;
[InfoBox("Every button action will toggle the states at the given indices between 0 and 90 degrees.")]
[SerializeField]
private List<ButtonAction> buttonActions;
[BoxGroup("Internal")] [SerializeField]
private List<Emission> 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];
}
}
/// <summary>
/// Switch all rotators specified by a given action.
/// </summary>
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<Rotator> list) => list != null && list.Count == stateCount;
}
}