using System.Collections.Generic; using System.Linq; using EscapeRoomEngine.Engine.Runtime.Measurements; using EscapeRoomEngine.Engine.Runtime.Modules; using UnityEngine; using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger; using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType; namespace EscapeRoomEngine.Engine.Runtime { public class Room { internal Passage entrance, exit; internal GameObject roomObject; internal bool LastRoom => exit == null; private readonly List _spaces = new(); private readonly List _puzzles = new(); private readonly List _doors = new(); internal Room(Passage entrance) { this.entrance = entrance; } internal void AddSpace(Space space, Passage spaceExit) { _spaces.Add(space); exit = spaceExit; } /// /// Solves all puzzles in this room. /// public void SkipRoom() { Logger.Log($"Skipping {this}...", LogType.PuzzleFlow); _puzzles.ForEach(puzzle => puzzle.PuzzleState.Solve()); if (_puzzles.Count == 0 && !LastRoom) { exit.fromOut.DoorState.Unlock(); } } public void EnterRoom() { entrance.toIn.DoorState.ExitFrom(); } internal void AddPuzzle(PuzzleModule puzzle) { _puzzles.Add(puzzle); puzzle.PuzzleState.PuzzleEvent += OnPuzzleEvent; } private void OnPuzzleEvent(PuzzleModule puzzle, PuzzleEventType type) { if (type == PuzzleEventType.Solved) { Measure.Solve((PuzzleModuleDescription)puzzle.description); if (LastRoom) { GameControl.Instance.StopGame(); } else if (_puzzles.All(p => p.PuzzleState.Solved)) { exit.fromOut.DoorState.Unlock(); } } } internal void AddDoor(DoorModule door) { _doors.Add(door); door.DoorState.DoorEvent += (_, type) => { // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault switch (type) { // generate a new room as soon as the player completes all puzzles in this one case DoorEventType.Unlocked when !LastRoom && door.Equals(exit.fromOut): Engine.DefaultEngine.GenerateRoom(); break; // start measurements on every puzzle as soon as the player enters the last room case DoorEventType.ExitedFrom when door.Equals(entrance.toIn) && Engine.DefaultEngine.CurrentRoom.Contains(this): _puzzles.ForEach(puzzle => Measure.StartMeasuring((PuzzleModuleDescription)puzzle.description)); Engine.DefaultEngine.HidePreviousRoom(); break; } }; } internal void InstantiateRoom(Transform parent, Vector3 offset, string name) { roomObject = new GameObject($"Room {name}"); roomObject.transform.SetParent(parent, false); roomObject.transform.localPosition = offset; for (var i = 0; i < _spaces.Count; i++) { _spaces[i].InstantiateSpace(roomObject.transform, i.ToString()); } entrance.ConnectDoors(); entrance.toIn.DoorState.Unlock(); } public override string ToString() { return roomObject.name; } } }