#nullable enable using System; using System.Collections; using NaughtyAttributes; using UnityEngine; using Random = UnityEngine.Random; public class Arena : MonoBehaviour { [Serializable] struct GladiatorEntrance { public Vector2 position; public Vector2 direction; } [SerializeField] [Required] GameFlowManager gameFlowManager = null!; //TODO Add some kind of "MinLength(1)" attribute [SerializeField] GladiatorEntrance[] spawners = null!; [SerializeField] [Required] ArenaStats stats = null!; [field: SerializeField] [field: Required] public Transform gladiatorParent { get; private set; } = null!; //TODO Add some kind of "MinLength(1)" attribute; [SerializeField] [Required] public AIEntity lightGladiator = null!; [SerializeField] [Required] public AIEntity regularGladiator = null!; [SerializeField] [Required] public AIEntity heavyGladiator = null!; [field: SerializeField] [field: Required] public Transform minionParent { get; private set; } = null!; [field: SerializeField] [field: Required] public Transform graveyard { get; private set; } = null!; SafeZone safeZone = null!; [field: SerializeField] int currWaveSize = 0; [SerializeField] AudioSource waveSource = null!; [SerializeField] AudioClip[] waveSounds = null!; [HideInInspector] public SoundManager soundManager = null!; void Awake() { safeZone = GetComponentInChildren(); soundManager = FindObjectOfType(); } void Start() => gameFlowManager.stateChanged += OnGameFlowStateChanged; void OnDestroy() => gameFlowManager.stateChanged -= OnGameFlowStateChanged; void SpawnEnemy(int spawnerIndex, AIEntity entityPrefab) { if (!gameFlowManager.CanDoAction) return; var gladiator = Instantiate(entityPrefab, gladiatorParent).GetComponent(); gladiator.arena = this; float randFloat = Random.Range(0.1f, 0.5f); Vector2 offset = new Vector2(randFloat, randFloat); gladiator.transform.position = spawners[spawnerIndex].position + offset; gladiator.direction = spawners[spawnerIndex].direction; gladiator.gameFlowManager = gameFlowManager; } IEnumerator SpawnEnemies() { yield return new WaitForSeconds(stats.initWaitToSpawn); currWaveSize = stats.initWaveSize; int currentSpawner = 0; int lightAmountSpawned = 0; int heavyAmountSpawned = 0; int amountSpawned = 0; int wave = 1; while(true){ soundManager.PlaySound(waveSource, waveSounds, randomPitch: true, createTempSourceIfBusy: true); while (amountSpawned < currWaveSize) { currentSpawner = Random.Range(0, spawners.Length); if(currWaveSize >= stats.regularBeforeLight && lightAmountSpawned <= stats.maxWaveSize * stats.lightRatio){ SpawnEnemy(currentSpawner, lightGladiator); lightAmountSpawned++; }else if(currWaveSize >= stats.regularBeforeHeavy && heavyAmountSpawned <= stats.maxWaveSize * stats.heavyRatio){ SpawnEnemy(currentSpawner, heavyGladiator); heavyAmountSpawned++; }else{ SpawnEnemy(currentSpawner, regularGladiator); } amountSpawned++; } if(wave++ >= stats.increaseWaveStep){ if((currWaveSize += stats.waveIncrease) > stats.maxWaveSize) currWaveSize=stats.maxWaveSize; // print(currWaveSize); } amountSpawned = 0; lightAmountSpawned = 0; heavyAmountSpawned = 0; yield return new WaitForSeconds(stats.secondsBetweenSpawners); } } public Vector3 GetMoatExtents() { return safeZone.GetMoatExtents(); } void OnGameFlowStateChanged(BaseState oldState, BaseState newState) { if (oldState is GameFlowManager.StartFlowState && newState is GameFlowManager.GameplayFlowState) StartCoroutine(SpawnEnemies()); } #if UNITY_EDITOR void OnDrawGizmosSelected() { Gizmos.color = Color.blue; foreach (GladiatorEntrance entrance in spawners) { Gizmos.DrawWireCube(entrance.position, Vector3.one); Gizmos.DrawLine(entrance.position, entrance.position + entrance.direction); } } #endif }