small fixes

This commit is contained in:
2023-03-22 07:54:00 +01:00
parent 307edb8491
commit 9c65d24685
481 changed files with 2432 additions and 33 deletions

View File

@@ -0,0 +1,39 @@
using EscapeRoomEngine.Engine.Runtime.Modules;
using NaughtyAttributes;
namespace EscapeRoomEngine.Desert.Runtime.Puzzle_A
{
/// <summary>
/// The main component for the symbol ball module.
/// </summary>
public class Ball : ModuleState
{
[BoxGroup("Internal")] [Required]
public Emission statusLight;
[BoxGroup("Internal")] [Required]
public Ring ring;
public bool StatusLight
{
set => statusLight.active = value;
}
public bool Active
{
set
{
statusLight.color = value ?
Engine.Runtime.Engine.Theme.puzzleColor.hdr
: Engine.Runtime.Engine.Theme.solvedColor.hdr;
ring.rotating = value;
if (!value)
{
ring.crystal.Active = false;
ring.symbols.ForEach(symbol => symbol.Active = false);
}
}
}
public override void SetModule(Module module) {}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b9b2d31478f94735a2e19e7c07a27f05
timeCreated: 1668705636

View File

@@ -0,0 +1,65 @@
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using JetBrains.Annotations;
using NaughtyAttributes;
using UnityEngine;
namespace EscapeRoomEngine.Desert.Runtime.Puzzle_A
{
/// <summary>
/// The rotating ring in the symbol ball module.
/// </summary>
public class Ring : MonoBehaviour
{
[Tooltip("Whether the ring is rotating.")]
public bool rotating = true;
[Tooltip("The current angle of the rotation.")]
public float rotationAngle;
[Tooltip("The range in degrees from the front of the module where a symbol should be lit up.")]
[MinMaxSlider(-180, 180)]
public Vector2 activeRange;
[BoxGroup("Internal")] [Required]
public Crystal crystal;
[BoxGroup("Internal")]
[ValidateInput("SymbolCount", "Must have same amount of symbols and slots.")]
public List<Symbol> symbols;
[BoxGroup("Internal")]
public List<Transform> symbolSlots;
private void Awake()
{
var angleDistance = 360f / symbols.Count;
List<Symbol> symbolInstances = new(symbols.Count);
for (var i = 0; i < symbols.Count; i++)
{
var symbol = Instantiate(symbols.RandomElement(), symbolSlots[i], false);
symbol.symbolPosition = i;
symbol.anglePosition = i * angleDistance;
symbolInstances.Add(symbol);
}
symbols = symbolInstances;
}
private void Update()
{
if(rotating)
{
transform.localRotation = Quaternion.AngleAxis(rotationAngle, Vector3.forward);
var activeSymbol = false;
symbols.ForEach(symbol =>
{
var angle = (rotationAngle - symbol.anglePosition) % 360;
var active = angle > activeRange.x && angle < activeRange.y || angle > 360 + activeRange.x;
symbol.Active = active;
activeSymbol |= active;
});
crystal.Active = activeSymbol;
}
}
[UsedImplicitly] private bool SymbolCount(List<Symbol> list) => list.Count == symbolSlots.Count;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7902f6a7fa0fd844f8ed93e3debd7778
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
using System;
using NaughtyAttributes;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
namespace EscapeRoomEngine.Desert.Runtime.Puzzle_A
{
public enum SymbolEventType
{
Activated, Deactivated
}
public static class SymbolEventExtensions
{
public static string Description(this SymbolEventType type, Symbol symbol)
{
var action = type switch
{
SymbolEventType.Activated => "activated",
SymbolEventType.Deactivated => "deactivated",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
return $"{symbol} was {action}";
}
}
public delegate void SymbolEventHandler(SymbolEventType e);
/// <summary>
/// The main component for the symbols on the symbol ring module.
/// </summary>
[RequireComponent(typeof(Emission))]
public class Symbol : MonoBehaviour
{
[Tooltip("The number of the symbol in the puzzle solution.")]
public int symbolNumber;
[BoxGroup("Internal")]
public int symbolPosition;
[BoxGroup("Internal")]
public float anglePosition;
public event SymbolEventHandler SymbolEvent;
/// <summary>
/// Whether the symbol is lit up. This is controlled by the <see cref="Ring"/>.
/// </summary>
public bool Active
{
set
{
var previous = _emission.active;
_emission.active = value;
if (previous != value)
{
OnSymbolEvent(value ? SymbolEventType.Activated : SymbolEventType.Deactivated);
}
}
}
private Emission _emission;
private void Awake()
{
_emission = GetComponent<Emission>();
}
private void Start()
{
Active = false;
}
private void OnSymbolEvent(SymbolEventType type)
{
Logger.Log(type.Description(this), LogType.PuzzleDetail);
SymbolEvent?.Invoke(type);
}
public override string ToString()
{
return name;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e099fd852792c34188dcf102aa895e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
using UnityEngine;
namespace EscapeRoomEngine.Desert.Runtime.Puzzle_A
{
/// <summary>
/// A <see cref="HoloButton"/> that includes the number of its assigned symbol.
/// </summary>
public class SymbolButton : HoloButton
{
[Tooltip("The number of the symbol assigned to this button.")]
public int symbolNumber;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d6620bee0f14224b11a19808d537cbd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,154 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
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 EscapeRoomEngine.Desert.Runtime.Puzzle_A
{
/// <summary>
/// The main component for the terminal module.
/// </summary>
[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<SymbolButton> symbols;
[BoxGroup("Internal")]
public List<Transform> symbolSlots;
private IOption<Symbol> _activeSymbol;
private Animator _animator;
private Ball _ball;
private void Awake()
{
_animator = GetComponent<Animator>();
List<SymbolButton> 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 = Engine.Runtime.Engine.Theme.puzzleColor.hdr;
symbols.ForEach(symbol => symbol.Enable());
break;
case PuzzleEventType.Solved:
_ball.Active = false;
terminalLight.color = 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<Symbol>.Of(symbol) : None<Symbol>.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<SymbolButton> list) => list.Count == symbolSlots.Count;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c5df397607f423a8cde06954f22a2bd
timeCreated: 1668762976