Files
Inter-Face-Off/Assets/Scripts/WindowSpawner.cs
2026-01-29 10:49:18 +00:00

170 lines
6.2 KiB
C#

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; }
[field: SerializeField] private GameObject PasswordField { get; set; }
[field: SerializeField] private GameObject LeaderboardObject { 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<WindowInteractions>();
windowBase.Interactions.SetAttachedTo(windowBase);
windowBase.Components = go.GetComponent<WindowComponents>();
windowBase.InstantiateWindowBase(creator: this);
}
public void AlertOfDespawnedWindow() => SpawnedWindowCount--;
private int SpawnyThingyMajig = 9000; // Sky chose dis
private void FixedUpdate()
{
/* Spawns new windows whilst active */
if (AutoSpawn)
{
/* Has a random choice for the PasswordField to show up */
if (SpawnyThingyMajig == 0)
{
PasswordField.SetActive(true);
SpawnyThingyMajig = Random.Range(2000, 10000);
}
else
{
SpawnyThingyMajig--;
}
/* Calculates the current max spawn time */
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
{
/* Makes sure the password overlay does not interfere */
PasswordField.SetActive(false);
/* Else checks if it should change the active scene */
if (Input.GetKey(KeyCode.Space) && !LeaderboardObject.activeSelf)
{
SceneController.ReloadScene();
}
else if (Input.GetKey(KeyCode.Tab) && !LeaderboardObject.activeSelf)
{
SceneController.Load(name: "MenuScene");
}
}
}
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);
}
}
}