using System; using Ext.B83.Unity.Attributes; using InterfaceOff.MainMenu; using InterfaceOff.WorldScene; using UnityEngine; using Random = UnityEngine.Random; namespace InterfaceOff { [Serializable] public struct SpawnableWindowType { [field: SerializeField, MonoScript] private string Typename { get; set; } public Type Type => Type.GetType(Typename); [field: SerializeField] public int SpawnWeight { get; private set; } } public class WindowSpawner : MonoBehaviour { [field: SerializeField] private GameObject SampleChild { get; set; } [field: SerializeField] private Canvas GameCanvas { get; set; } [field: SerializeField] private GameObject DeathInfo { get; set; } [field: SerializeField] private SpawnableWindowType[] WindowTypes { get; set; } [field: SerializeField] private GameObject Parent { get; set; } private int TotalSpawnWeight { get; set; } [field: SerializeField] public int SpawnedWindowCount { get; private set; } [field: SerializeField] public bool AutoSpawn { get; private set; } = true; private int TimeTillNextSpawn { get; set; } private void Awake() { /* Logs the amount of types found and errors if there is none */ Debug.Log($"Found [{WindowTypes.Length}] different window types "); if (WindowTypes.Length == 0) { Debug.LogError("Could not find any window types"); return; } /* Calculates the total spawn weight */ TotalSpawnWeight = 0; foreach (SpawnableWindowType type in WindowTypes) { TotalSpawnWeight += type.SpawnWeight; } } private Type GetRandomWindowType() { int currentTypeWeight = Random.Range(0, TotalSpawnWeight); foreach (SpawnableWindowType type in WindowTypes) { currentTypeWeight -= type.SpawnWeight; if (currentTypeWeight <= 0) { return type.Type; } } return WindowTypes[0].Type; } private void SpawnNewRandomWindow() { /* Creates the gameobject with a random class */ GameObject go = Instantiate(SampleChild, Parent.transform); go.SetActive(true); Type type = GetRandomWindowType(); go.name = type.Name; WindowBase windowBase = go.AddComponent(type) as WindowBase; /* Checks it created correctly before instantiating further */ if (DebugUtils.IsNull(windowBase)) { Debug.LogError("How did this happen"); return; } /* Updates the window trackers */ SpawnedWindowCount++; /* Makes sure the WindowInteractions and WindowComponents are set up before passing to user code */ windowBase.Interactions = go.GetComponent(); windowBase.Interactions.SetAttachedTo(windowBase); windowBase.Components = go.GetComponent(); windowBase.InstantiateWindowBase(creator: this); } public void AlertOfDespawnedWindow() => SpawnedWindowCount--; private void FixedUpdate() { /* Spawns new windows whilst active */ if (AutoSpawn) { const int TICKS_PER_SECOND = 20; // Unity constant const int MIN_SPAWN_TIME = 2 * TICKS_PER_SECOND; const int MAX_SPAWN_TIME = 5 * TICKS_PER_SECOND; int currentMaxSpawnTime = MAX_SPAWN_TIME - (int)(ScoreTracker.CurrentScore() / DifficultyManager.DifficultyEffect); currentMaxSpawnTime = Math.Clamp(currentMaxSpawnTime, MIN_SPAWN_TIME + 1, MAX_SPAWN_TIME); /* Decreases the spawn counter and spawns if at 0 */ TimeTillNextSpawn = Math.Max(0, TimeTillNextSpawn - 1); if (TimeTillNextSpawn == 0) { float difficulty = DifficultyManager.DifficultyMultiplier; TimeTillNextSpawn = Random.Range((int)(MIN_SPAWN_TIME * difficulty), (int)(currentMaxSpawnTime * difficulty)); SpawnNewRandomWindow(); } } /* Else checks if it should reload the scene */ else if (Input.GetKey(KeyCode.Space)) { SceneController.ReloadScene(); } } public void StartEndSequence() { /* Destroys all children and stops them from spawning */ AutoSpawn = false; foreach (Transform child in Parent.transform) { WindowBase window = child.GetComponent(); if (DebugUtils.IsNotNull(window)) { window.DestroyWindow(); } } /* Makes the death text visible to the player */ DeathInfo.SetActive(true); } } }