Files
Northbound/Assets/Northbound/Gameplay/Waves/WaveDirector.cs
T

111 lines
3.6 KiB
C#

using System.Collections.Generic;
using Northbound.Gameplay.Enemy;
using Northbound.Gameplay.World;
using UnityEngine;
namespace Northbound.Gameplay.Waves
{
public sealed class WaveDirector : MonoBehaviour
{
[SerializeField] private float firstWaveDelay = 15f;
[SerializeField] private float waveInterval = 90f;
[SerializeField] private Material gruntMaterial;
[SerializeField] private Material raiderMaterial;
[SerializeField] private Material eliteMaterial;
[SerializeField] private EnemyPursuitDefinition pursuitDefinition;
private float nextWaveAt;
private int wave;
public int CurrentWave => wave;
public float NextWaveIn => Mathf.Max(0f, nextWaveAt - Time.time);
private void Start()
{
nextWaveAt = Time.time + firstWaveDelay;
PublishStatus(0);
}
private void Update()
{
var state = SharedGameState.Instance;
if (state == null || state.IsDefeated || state.IsVictorious)
{
return;
}
if (Time.time >= nextWaveAt)
{
BeginWave();
}
PublishStatus(state.ResonanceSnapshot);
}
public void Configure(Material grunt, Material raider, Material elite, EnemyPursuitDefinition pursuit)
{
gruntMaterial = grunt;
raiderMaterial = raider;
eliteMaterial = elite;
pursuitDefinition = pursuit;
}
private void BeginWave()
{
wave++;
var state = SharedGameState.Instance;
var resonance = Mathf.Min(3, state.CountEnemyPortals());
var enemyPortals = new List<PortalSite>();
foreach (var portal in state.Portals)
{
if (portal.State == PortalState.Enemy)
{
enemyPortals.Add(portal);
}
}
var spawnCount = 3 + wave * 2;
for (var index = 0; index < spawnCount && enemyPortals.Count > 0; index++)
{
var portal = enemyPortals[index % enemyPortals.Count];
var role = ResolveRole(index);
var offset = new Vector3((index % 3 - 1) * 1.4f, 1f, 2f + index / 3f);
SpawnEnemy(portal.transform.position + offset, role, resonance);
}
nextWaveAt = Time.time + waveInterval;
PublishStatus(resonance);
}
private EnemyRole ResolveRole(int index)
{
if (wave >= 3 && index == 0)
{
return EnemyRole.Elite;
}
return index % 4 == 3 ? EnemyRole.Raider : EnemyRole.Grunt;
}
private void SpawnEnemy(Vector3 position, EnemyRole role, int resonance)
{
var enemy = GameObject.CreatePrimitive(role == EnemyRole.Elite ? PrimitiveType.Cube : PrimitiveType.Capsule);
enemy.name = $"Wave {wave} {role}";
enemy.transform.position = position;
enemy.transform.localScale = role == EnemyRole.Elite ? Vector3.one * 1.6f : Vector3.one;
var material = role switch
{
EnemyRole.Raider => raiderMaterial,
EnemyRole.Elite => eliteMaterial,
_ => gruntMaterial
};
enemy.AddComponent<EnemyAgent>().Configure(role, resonance, material, pursuitDefinition);
}
private void PublishStatus(int resonance)
{
SharedGameState.Instance?.SetWaveStatus(wave, resonance, NextWaveIn);
}
}
}