Files
FORT-BO/Assets/CONTENT/FEATURES/MapRadar/MapTargetController.cs
T
2026-08-21 17:59:13 +03:00

175 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
[DisallowMultipleComponent]
public sealed class MapTargetController : MonoBehaviour
{
[Header("Target Types")]
[SerializeField] private TargetConfig[] randomTargetConfigs = Array.Empty<TargetConfig>();
[SerializeField] private bool showLiveTargetVisuals;
[Header("Current Wave (Runtime)")]
[SerializeField, Min(0)] private int currentWave;
[SerializeField] private List<MapTarget> currentWaveTargets = new();
private readonly List<MapTarget> pooledTargets = new();
private readonly Dictionary<int, MapTarget> targetsById = new();
private readonly HashSet<int> synchronizedTargetIds = new();
private MapCoordinateSystem coordinateSystem;
private Transform targetParent;
private MapPlayer player;
public IReadOnlyList<MapTarget> Targets => currentWaveTargets;
public IReadOnlyList<TargetConfig> TargetConfigs => randomTargetConfigs;
public int CurrentWave => currentWave;
private void OnValidate()
{
currentWave = Mathf.Max(0, currentWave);
}
public void Configure(
MapCoordinateSystem newCoordinateSystem,
Transform newTargetParent,
MapPlayer newPlayer)
{
coordinateSystem = newCoordinateSystem;
targetParent = newTargetParent != null ? newTargetParent : transform;
player = newPlayer;
pooledTargets.Clear();
targetsById.Clear();
currentWaveTargets.Clear();
foreach (MapTarget existingTarget in targetParent.GetComponentsInChildren<MapTarget>(true))
{
existingTarget.SetVisualsVisible(false);
existingTarget.gameObject.SetActive(false);
pooledTargets.Add(existingTarget);
}
}
public void ApplyNetworkTargets(
IReadOnlyList<MapTargetNetworkState> states,
int wave)
{
currentWave = Mathf.Max(0, wave);
synchronizedTargetIds.Clear();
for (int index = 0; index < states.Count; index++)
{
MapTargetNetworkState state = states[index];
TargetConfig config = GetConfig(state.ConfigIndex);
if (config == null || config.TargetPrefab == null)
continue;
synchronizedTargetIds.Add(state.TargetId);
if (!targetsById.TryGetValue(state.TargetId, out MapTarget target) || target == null)
{
target = GetPooledTarget(config);
if (target == null)
target = Instantiate(config.TargetPrefab, targetParent);
targetsById[state.TargetId] = target;
currentWaveTargets.Add(target);
}
target.name = $"Wave {currentWave} - {config.name} - {state.TargetId}";
target.Configure(config, coordinateSystem, player);
target.ApplyNetworkState(state);
target.SetVisualsVisible(showLiveTargetVisuals);
target.gameObject.SetActive(true);
}
for (int index = currentWaveTargets.Count - 1; index >= 0; index--)
{
MapTarget target = currentWaveTargets[index];
if (target != null && synchronizedTargetIds.Contains(target.TargetId))
continue;
RetireTarget(target);
currentWaveTargets.RemoveAt(index);
}
}
public TargetConfig GetConfig(int index) =>
index >= 0 && index < randomTargetConfigs.Length
? randomTargetConfigs[index]
: null;
public int GetRandomValidConfigIndex()
{
if (randomTargetConfigs == null || randomTargetConfigs.Length == 0)
return -1;
int startIndex = UnityEngine.Random.Range(0, randomTargetConfigs.Length);
for (int offset = 0; offset < randomTargetConfigs.Length; offset++)
{
int index = (startIndex + offset) % randomTargetConfigs.Length;
TargetConfig config = randomTargetConfigs[index];
if (config != null && config.TargetPrefab != null)
return index;
}
return -1;
}
public bool HasValidConfiguration() =>
coordinateSystem != null && coordinateSystem.HasValidCorners() &&
GetRandomValidConfigIndex() >= 0;
public void SetTargetVisualsVisible(bool isVisible)
{
showLiveTargetVisuals = isVisible;
foreach (MapTarget target in currentWaveTargets)
{
if (target != null)
target.SetVisualsVisible(isVisible);
}
}
public MapTarget GetTarget(int index) =>
index >= 0 && index < currentWaveTargets.Count
? currentWaveTargets[index]
: null;
public bool StartNextWave()
{
MapController mapController = FindFirstObjectByType<MapController>();
return mapController != null && mapController.StartNextWave();
}
private MapTarget GetPooledTarget(TargetConfig config)
{
for (int index = pooledTargets.Count - 1; index >= 0; index--)
{
MapTarget candidate = pooledTargets[index];
if (candidate == null)
{
pooledTargets.RemoveAt(index);
continue;
}
if (candidate.GetType() != config.TargetPrefab.GetType())
continue;
pooledTargets.RemoveAt(index);
return candidate;
}
return null;
}
private void RetireTarget(MapTarget target)
{
if (target == null)
return;
targetsById.Remove(target.TargetId);
target.SetVisualsVisible(false);
target.gameObject.SetActive(false);
if (!pooledTargets.Contains(target))
pooledTargets.Add(target);
}
}