114 lines
4.3 KiB
C#
114 lines
4.3 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.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<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;
|
|
}
|
|
} |