diff --git a/Assets/Editor/WaveConfigCustomInspector.cs b/Assets/Editor/WaveConfigCustomInspector.cs index 8ee92ad..e56df76 100644 --- a/Assets/Editor/WaveConfigCustomInspector.cs +++ b/Assets/Editor/WaveConfigCustomInspector.cs @@ -10,12 +10,14 @@ namespace GatherAndDefend.LevelEditor { EditorGUILayout.HelpBox(@"How to use : - ConstantSpawn: Drag the chosen Enemy and insert the number to make in Count +- GroupSpawn: Each group contains enemies, and the time to trigger in float format for minutes. - GameDuration : Duration of the game, in minutes - Usage : Drop this config into a level -- Creation interval is determined by the game duration and the number of enemies to create +- The creation interval is determined by the game duration and the number of enemies to create -Important consideration : -- You must assign at least 1 enemy of Count of at least 1 to play.", MessageType.None); +Important consideration : +- You must assign at least 1 enemy of Count of at least 1 to play. +- GameDuration cannot be 0.", MessageType.None); base.OnInspectorGUI(); } } diff --git a/Assets/Scripts/LevelConfig/WaveConfig.cs b/Assets/Scripts/LevelConfig/WaveConfig.cs index 67b595d..34c1052 100644 --- a/Assets/Scripts/LevelConfig/WaveConfig.cs +++ b/Assets/Scripts/LevelConfig/WaveConfig.cs @@ -1,6 +1,11 @@ using System.Collections.Generic; using UnityEngine; - +[System.Serializable] +public class GroupList +{ + public List groupSpawn; + public float triggerTime; +} [CreateAssetMenu(menuName = "Gather And Defend/Levels/WaveConfig")] public class WaveConfig : ScriptableObject { @@ -8,9 +13,9 @@ public class WaveConfig : ScriptableObject [SerializeField] private List _constantSpawn = new List(); [SerializeField] - private List _groupSpawn = new List(); //TODO: Turn into List of list later on + private List _nestedGroupSpawn = new List(); [SerializeField] - private float _gameDuration = 0; + private float _gameDuration = 1; private float _enemySpawndOnStart = 0; private int _enemySum = 0; public List ConstantSpawn @@ -20,17 +25,35 @@ public class WaveConfig : ScriptableObject return _constantSpawn; } } + + /** + * Contains every list of enemy groups + */ + public List NestedGroupSpawn + { + get + { + return _nestedGroupSpawn; + } + } public float GetInterval() { - float interval = _gameDuration * 60.0f / (_enemySum > 0 ? _enemySum.ToFloat() : SumCount()) ; + float interval = _gameDuration * 60.0f / (_enemySum > 0 ? _enemySum.ToFloat() : SumCount()); return interval; } + /** + * Returns the updated game interval after adjusting to enemies spawned at the start + */ public float GetUpdatedInterval() { _enemySpawndOnStart++; float interval = Mathf.Max(_gameDuration * 60.0f / (_enemySum - _enemySpawndOnStart).ToFloat(), 0); return interval; } + + /** + * Returns a random enemy among the constantSpawn list + */ public EnemyType GetRandomSpawn() { if (_constantSpawn.Count == 1) @@ -39,6 +62,10 @@ public class WaveConfig : ScriptableObject } return _constantSpawn[Random.Range(0, _constantSpawn.Count - 1)]; } + + /** + * Returns the count of enemies to spawn + */ private float SumCount() { foreach (EnemyType enemy in _constantSpawn) @@ -47,10 +74,4 @@ public class WaveConfig : ScriptableObject } return _enemySum.ToFloat(); } - - public List getGroupList() - { - return _groupSpawn; - } - } diff --git a/Assets/Scripts/LevelConfig/WaveObserver.cs b/Assets/Scripts/LevelConfig/WaveObserver.cs index f1ee0e3..42b5ad4 100644 --- a/Assets/Scripts/LevelConfig/WaveObserver.cs +++ b/Assets/Scripts/LevelConfig/WaveObserver.cs @@ -1,26 +1,36 @@ using System.Collections.Generic; using UnityEngine; -using System; public class WaveObserver : Singleton { private List _subjects = new List(); private List _aliveEnemyCount = new List(); private List _copyConstantSpawn; + private List _copyGroupSpawn; + private List _groupSpawnTimers; private WaveConfig _levelConfig; private const int MAXTOUGHNESS = 10; private int _spawnerTiming = 0; private List _intervalTiming = new List(); + private bool _once = true; + private int _currentGroupIndex = 0; public WaveConfig LevelConfig { set { _levelConfig = value; _copyConstantSpawn = new List(); + _copyGroupSpawn = new List(); + _groupSpawnTimers = new List(); foreach (EnemyType enemy in _levelConfig.ConstantSpawn) { _copyConstantSpawn.Add(enemy.Count); } + for (int index = 0; index < _levelConfig.NestedGroupSpawn.Count; index++) + { + _copyGroupSpawn.Add(_levelConfig.NestedGroupSpawn[index]); + _groupSpawnTimers.Add(_levelConfig.NestedGroupSpawn[index].triggerTime); + } } } @@ -35,6 +45,12 @@ public class WaveObserver : Singleton _subjects.Add(spawnerSubject); _aliveEnemyCount.Add(0); _intervalTiming.Add(++_spawnerTiming); + // Ensures that only one spawner keeps track of the grouped spawn timer. + if (_once) + { + _once = false; + spawnerSubject.GroupSpawnTimers = _groupSpawnTimers; + } } /** @@ -139,4 +155,21 @@ public class WaveObserver : Singleton spawnerTile.ChangeSpawnSpeed(_levelConfig.GetInterval() * _intervalTiming[index]); _intervalTiming.Remove(index); } + + /** + * Called when it is time to spawn a group + * Assigns a random element of the group to a random spawner + */ + public void NotifyGroupSpawn() + { + System.Random rand = new System.Random(); + foreach (EnemyType groupEnemy in _copyGroupSpawn[_currentGroupIndex].groupSpawn) + { + for (int i = 0; i < groupEnemy.Count; i++) + { + _subjects[rand.Next(_subjects.Count)].TriggerSpawn(groupEnemy.GetEnemyObject()); + } + } + _currentGroupIndex++; + } } diff --git a/Assets/Scripts/Tiles/SpawnerTile.cs b/Assets/Scripts/Tiles/SpawnerTile.cs index 38450a7..7aac2ca 100644 --- a/Assets/Scripts/Tiles/SpawnerTile.cs +++ b/Assets/Scripts/Tiles/SpawnerTile.cs @@ -16,6 +16,14 @@ public class SpawnerTile : LevelTile private WaveObserver _observer; private bool _stopped = false; private bool _cooldownEnded = false; + private List _groupSpawnTimers = new List(); + public List GroupSpawnTimers + { + set + { + _groupSpawnTimers = value; + } + } public override void LevelStart() @@ -24,7 +32,7 @@ public class SpawnerTile : LevelTile _observer.Attach(this); if (_spawnOnStart && _lifetime <= 0) { - _prefab.Create(Position, parent: LevelManager.Instance.LevelTransform); + TriggerSpawn(_prefab); _observer.NotifyOnStart(this); } } @@ -36,6 +44,14 @@ public class SpawnerTile : LevelTile { _spawnCounter += Time.deltaTime; } + if (_groupSpawnTimers.Count > 0) + { + if (_lifetime / 60 > _groupSpawnTimers[0]) + { + _groupSpawnTimers.RemoveAt(0); + _observer.NotifyGroupSpawn(); + } + } if (_spawnCounter < _spawnSpeed) return; _spawnCounter = 0; @@ -45,7 +61,7 @@ public class SpawnerTile : LevelTile _cooldownEnded = true; return; } - _prefab.Create(Position, parent: LevelManager.Instance.LevelTransform); + TriggerSpawn(_prefab); _observer.NotifySpawned(this); } public override bool Equals(ILevelObject other) @@ -90,13 +106,13 @@ public class SpawnerTile : LevelTile _spawnOnStart = dict[nameof(_spawnOnStart)].ToBool(); } - public GameObject Prefab - { - set + public GameObject Prefab + { + set { - _prefab = value; - } - get + _prefab = value; + } + get { return _prefab; } @@ -110,4 +126,13 @@ public class SpawnerTile : LevelTile { _spawnSpeed = value; } + + /** + * Instantly spawns an enemy. + * Used for GroupSpawn + */ + public void TriggerSpawn(GameObject enemy) + { + enemy.Create(Position, parent: LevelManager.Instance.LevelTransform); + } } \ No newline at end of file diff --git a/Assets/WaveConfig/Config01.asset b/Assets/WaveConfig/Config01.asset index 5ae7f4e..0a3812f 100644 --- a/Assets/WaveConfig/Config01.asset +++ b/Assets/WaveConfig/Config01.asset @@ -15,9 +15,17 @@ MonoBehaviour: _constantSpawn: - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} _count: 5 - _groupSpawn: - - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} - _count: 3 - - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} - _count: 1 - _gameDuration: 1 + _nestedGroupSpawn: + - groupSpawn: + - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} + _count: 3 + - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} + _count: 1 + triggerTime: 0.5 + - groupSpawn: + - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} + _count: 1 + - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} + _count: 2 + triggerTime: 0 + _gameDuration2: 5