Files
Inter-Face-Off/Assets/Scripts/WindowSpawner.cs
2026-01-22 16:14:45 +00:00

145 lines
5.2 KiB
C#

using System;
using Ext.B83.Unity.Attributes;
using InterfaceOff.WorldScene;
using UnityEngine;
using UnityEngine.SceneManagement;
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; }
public static float DifficultyMultiplier = 1f;
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<WindowInteractions>();
windowBase.Interactions.SetAttachedTo(windowBase);
windowBase.Components = go.GetComponent<WindowComponents>();
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();
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)
{
TimeTillNextSpawn = Random.Range((int)(MIN_SPAWN_TIME * DifficultyMultiplier), (int)(currentMaxSpawnTime * DifficultyMultiplier));
SpawnNewRandomWindow();
}
}
/* Else checks if it should reload the scene */
else if (Input.GetKey(KeyCode.Space))
{
int sceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(sceneIndex);
}
}
public void StartEndSequence()
{
/* Destroys all children and stops them from spawning */
AutoSpawn = false;
foreach (Transform child in Parent.transform)
{
WindowBase window = child.GetComponent<WindowBase>();
if (DebugUtils.IsNotNull(window))
{
window.DestroyWindow();
}
}
/* Makes the death text visible to the player */
DeathInfo.SetActive(true);
}
}
}