Map mehanic ready to multiplayer
This commit is contained in:
@@ -1,100 +1,534 @@
|
||||
using System;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class MapController : MonoBehaviour
|
||||
[RequireComponent(typeof(NetworkObject))]
|
||||
public sealed class MapController : NetworkBehaviour
|
||||
{
|
||||
[Header("Main References")]
|
||||
[SerializeField] private MapCrosshairController crosshair = null;
|
||||
[SerializeField] private MapCoordinateSystem coordinateSystem = null;
|
||||
[SerializeField] private MapPlayer mapPlayer = null;
|
||||
[SerializeField] private MapCrosshairController crosshair;
|
||||
[SerializeField] private MapCoordinateSystem coordinateSystem;
|
||||
[SerializeField] private MapPlayer mapPlayer;
|
||||
[SerializeField] private RoundGameLoopController roundGameLoop;
|
||||
[SerializeField] private NetworkBaseHealth baseHealth;
|
||||
|
||||
[Header("Target System")]
|
||||
[SerializeField] private MapTargetController targetController = null;
|
||||
[SerializeField] private Transform targetParent = null;
|
||||
[SerializeField] private MapTargetController targetController;
|
||||
[SerializeField] private Transform targetParent;
|
||||
[SerializeField, Min(0.02f)] private float simulationStep = 0.1f;
|
||||
|
||||
[Header("Radar System")]
|
||||
[SerializeField] private MapRadarController radarController = null;
|
||||
[SerializeField] private MapRadarController radarController;
|
||||
[FormerlySerializedAs("targetPrefab")]
|
||||
[SerializeField] private MapTarget radarMarkPrefab = null;
|
||||
[SerializeField] private MapTarget radarMarkPrefab;
|
||||
|
||||
[Header("Crosshair Objects")]
|
||||
[SerializeField] private Transform relayX = null;
|
||||
[SerializeField] private Transform relayY = null;
|
||||
[SerializeField] private Transform crosshairVisual = null;
|
||||
[SerializeField] private Transform relayX;
|
||||
[SerializeField] private Transform relayY;
|
||||
[SerializeField] private Transform crosshairVisual;
|
||||
|
||||
[Header("Input")]
|
||||
[SerializeField, Min(0f)] private float movementSpeed = 1f;
|
||||
[SerializeField] private bool useKeyboardInput = true;
|
||||
[Header("Pseudo Shot")]
|
||||
[SerializeField, Min(0.01f)] private float hitRadius = 0.65f;
|
||||
[SerializeField, Min(1)] private int shotDamage = 1;
|
||||
[SerializeField] private MissileType pseudoMissileType = MissileType.Standard;
|
||||
[SerializeField] private bool ignoreMissileTypeForPrototype = true;
|
||||
|
||||
[Header("Network Events")]
|
||||
[SerializeField] private UnityEvent<int> waveStarted;
|
||||
[SerializeField] private UnityEvent<bool> shotResolved;
|
||||
[SerializeField] private UnityEvent allTargetsResolved;
|
||||
[SerializeField] private UnityEvent allTargetsDestroyed;
|
||||
|
||||
private readonly NetworkVariable<Vector2> crosshairCoordinates = new(
|
||||
new Vector2(5f, 5f), NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
private readonly NetworkVariable<int> currentWave = new(
|
||||
0, NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
private readonly NetworkVariable<double> radarReadyAt = new(
|
||||
0d, NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
private readonly NetworkVariable<MapShotResultState> lastShotResult = new(
|
||||
default, NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
private readonly NetworkVariable<uint> resolvedSequence = new(
|
||||
0, NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
private readonly NetworkVariable<uint> destroyedSequence = new(
|
||||
0, NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
|
||||
private readonly NetworkList<MapTargetNetworkState> activeTargets = new();
|
||||
private readonly NetworkList<Vector2> radarMarks = new();
|
||||
|
||||
private float simulationAccumulator;
|
||||
private int nextTargetId = 1;
|
||||
private int initialTargetCount;
|
||||
private int escapedTargetCount;
|
||||
private bool waveIsActive;
|
||||
private bool roundEventsBound;
|
||||
|
||||
public MapCoordinateSystem CoordinateSystem => coordinateSystem;
|
||||
public Transform CrosshairVisual => crosshairVisual;
|
||||
public Vector2 CrosshairCoordinates => crosshairCoordinates.Value;
|
||||
public int CurrentWave => currentWave.Value;
|
||||
public int ActiveTargetCount => activeTargets.Count;
|
||||
public bool WaveIsActive => waveIsActive;
|
||||
public double RadarCooldownRemaining => IsSpawned && NetworkManager != null
|
||||
? Math.Max(0d, radarReadyAt.Value - NetworkManager.ServerTime.Time)
|
||||
: 0d;
|
||||
|
||||
private void Awake()
|
||||
public event Action<int> WaveStarted;
|
||||
public event Action<MapShotResultState> ShotResolved;
|
||||
public event Action AllTargetsResolved;
|
||||
public event Action AllTargetsDestroyed;
|
||||
|
||||
private void Awake() => ConfigurePresentation();
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (mapPlayer != null)
|
||||
mapPlayer.Configure(coordinateSystem);
|
||||
simulationStep = Mathf.Max(0.02f, simulationStep);
|
||||
hitRadius = Mathf.Max(0.01f, hitRadius);
|
||||
shotDamage = Mathf.Max(1, shotDamage);
|
||||
}
|
||||
|
||||
if (targetController != null)
|
||||
targetController.Configure(coordinateSystem, targetParent, mapPlayer);
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
activeTargets.OnListChanged += HandleTargetListChanged;
|
||||
radarMarks.OnListChanged += HandleRadarListChanged;
|
||||
crosshairCoordinates.OnValueChanged += HandleCrosshairChanged;
|
||||
currentWave.OnValueChanged += HandleWaveChanged;
|
||||
radarReadyAt.OnValueChanged += HandleRadarReadyAtChanged;
|
||||
lastShotResult.OnValueChanged += HandleShotResultChanged;
|
||||
resolvedSequence.OnValueChanged += HandleResolvedSequenceChanged;
|
||||
destroyedSequence.OnValueChanged += HandleDestroyedSequenceChanged;
|
||||
|
||||
ConfigurePresentation();
|
||||
BindRoundEvents();
|
||||
ApplyPresentation();
|
||||
|
||||
if (IsServer && roundGameLoop != null &&
|
||||
roundGameLoop.Phase == RoundPhase.WorkInProgress && currentWave.Value == 0)
|
||||
StartNextWaveOnServer();
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
activeTargets.OnListChanged -= HandleTargetListChanged;
|
||||
radarMarks.OnListChanged -= HandleRadarListChanged;
|
||||
crosshairCoordinates.OnValueChanged -= HandleCrosshairChanged;
|
||||
currentWave.OnValueChanged -= HandleWaveChanged;
|
||||
radarReadyAt.OnValueChanged -= HandleRadarReadyAtChanged;
|
||||
lastShotResult.OnValueChanged -= HandleShotResultChanged;
|
||||
resolvedSequence.OnValueChanged -= HandleResolvedSequenceChanged;
|
||||
destroyedSequence.OnValueChanged -= HandleDestroyedSequenceChanged;
|
||||
UnbindRoundEvents();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
activeTargets.Dispose();
|
||||
radarMarks.Dispose();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!roundEventsBound)
|
||||
BindRoundEvents();
|
||||
if (radarController != null)
|
||||
radarController.Configure(coordinateSystem, targetController, radarMarkPrefab);
|
||||
|
||||
if (crosshair == null)
|
||||
radarController.SetCooldownRemaining((float)RadarCooldownRemaining);
|
||||
if (!IsServer || !IsSpawned || !waveIsActive)
|
||||
return;
|
||||
|
||||
crosshair.Configure(
|
||||
coordinateSystem,
|
||||
relayX,
|
||||
relayY,
|
||||
crosshairVisual,
|
||||
movementSpeed,
|
||||
useKeyboardInput,
|
||||
targetController);
|
||||
|
||||
simulationAccumulator += Time.deltaTime;
|
||||
while (simulationAccumulator >= simulationStep)
|
||||
{
|
||||
simulationAccumulator -= simulationStep;
|
||||
SimulateTargets(simulationStep);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHorizontalAxis(float value)
|
||||
public void SetHorizontalNormalized(float value)
|
||||
{
|
||||
if (crosshair != null)
|
||||
crosshair.SetHorizontalAxis(value);
|
||||
Vector2 next = crosshairCoordinates.Value;
|
||||
next.x = Mathf.Clamp01(value) * MapCoordinateSystem.CoordinateMaximum;
|
||||
RequestCrosshairCoordinates(next);
|
||||
}
|
||||
|
||||
public void SetVerticalAxis(float value)
|
||||
public void SetVerticalNormalized(float value)
|
||||
{
|
||||
if (crosshair != null)
|
||||
crosshair.SetVerticalAxis(value);
|
||||
Vector2 next = crosshairCoordinates.Value;
|
||||
next.y = Mathf.Clamp01(value) * MapCoordinateSystem.CoordinateMaximum;
|
||||
RequestCrosshairCoordinates(next);
|
||||
}
|
||||
|
||||
public Vector2 GetCrosshairCoordinates()
|
||||
public void SetHorizontalAxis(float value) =>
|
||||
SetHorizontalNormalized(Mathf.InverseLerp(-1f, 1f, value));
|
||||
public void SetVerticalAxis(float value) =>
|
||||
SetVerticalNormalized(Mathf.InverseLerp(-1f, 1f, value));
|
||||
public Vector2 GetCrosshairCoordinates() => crosshairCoordinates.Value;
|
||||
|
||||
public void RequestPseudoFire()
|
||||
{
|
||||
return crosshair != null ? crosshair.GetCrosshairCoordinates() : Vector2.zero;
|
||||
if (!IsSpawned)
|
||||
return;
|
||||
if (IsServer)
|
||||
ResolvePseudoShotOnServer();
|
||||
else
|
||||
RequestPseudoFireRpc();
|
||||
}
|
||||
|
||||
public void CreateAndPlaceTargets()
|
||||
public void RequestRadarScan()
|
||||
{
|
||||
if (targetController != null)
|
||||
targetController.CreateAndPlaceTargets();
|
||||
if (!IsSpawned)
|
||||
return;
|
||||
if (IsServer)
|
||||
ScanRadarOnServer();
|
||||
else
|
||||
RequestRadarScanRpc();
|
||||
}
|
||||
|
||||
public bool ActivateRadar()
|
||||
{
|
||||
if (!IsSpawned || RadarCooldownRemaining > 0d)
|
||||
return false;
|
||||
RequestRadarScan();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void CreateAndPlaceTargets() => StartNextWave();
|
||||
|
||||
public bool StartNextWave()
|
||||
{
|
||||
return targetController != null && targetController.StartNextWave();
|
||||
if (!IsSpawned)
|
||||
return false;
|
||||
if (IsServer)
|
||||
return StartNextWaveOnServer();
|
||||
RequestStartNextWaveRpc();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetNearestTarget(out MapTarget target, out float distance)
|
||||
{
|
||||
if (crosshair != null)
|
||||
return crosshair.TryGetNearestTarget(out target, out distance);
|
||||
|
||||
target = null;
|
||||
distance = -1f;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ActivateRadar()
|
||||
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
||||
private void SetCrosshairCoordinatesRpc(Vector2 coordinates) =>
|
||||
SetCrosshairCoordinatesOnServer(coordinates);
|
||||
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
||||
private void RequestPseudoFireRpc() => ResolvePseudoShotOnServer();
|
||||
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
||||
private void RequestRadarScanRpc() => ScanRadarOnServer();
|
||||
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
||||
private void RequestStartNextWaveRpc() => StartNextWaveOnServer();
|
||||
|
||||
private void RequestCrosshairCoordinates(Vector2 coordinates)
|
||||
{
|
||||
return radarController != null && radarController.ActivateRadar();
|
||||
if (!IsSpawned)
|
||||
return;
|
||||
if (IsServer)
|
||||
SetCrosshairCoordinatesOnServer(coordinates);
|
||||
else
|
||||
SetCrosshairCoordinatesRpc(coordinates);
|
||||
}
|
||||
|
||||
private void SetCrosshairCoordinatesOnServer(Vector2 coordinates)
|
||||
{
|
||||
if (!IsServer)
|
||||
return;
|
||||
crosshairCoordinates.Value = coordinateSystem != null
|
||||
? coordinateSystem.ClampCoordinates(coordinates)
|
||||
: new Vector2(
|
||||
Mathf.Clamp(coordinates.x, 0f, MapCoordinateSystem.CoordinateMaximum),
|
||||
Mathf.Clamp(coordinates.y, 0f, MapCoordinateSystem.CoordinateMaximum));
|
||||
}
|
||||
|
||||
private bool StartNextWaveOnServer()
|
||||
{
|
||||
if (!IsServer || targetController == null ||
|
||||
!targetController.HasValidConfiguration())
|
||||
{
|
||||
Debug.LogWarning("[Map] Cannot start target wave: map or target configs are incomplete.", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
activeTargets.Clear();
|
||||
radarMarks.Clear();
|
||||
currentWave.Value++;
|
||||
escapedTargetCount = 0;
|
||||
initialTargetCount = 0;
|
||||
waveIsActive = true;
|
||||
simulationAccumulator = 0f;
|
||||
|
||||
for (int index = 0; index < targetController.TargetsPerWave; index++)
|
||||
{
|
||||
int configIndex = targetController.GetRandomValidConfigIndex();
|
||||
TargetConfig config = targetController.GetConfig(configIndex);
|
||||
if (config == null)
|
||||
continue;
|
||||
|
||||
Vector2 coordinates = new(
|
||||
UnityEngine.Random.Range(0f, MapCoordinateSystem.CoordinateMaximum),
|
||||
UnityEngine.Random.Range(0f, MapCoordinateSystem.CoordinateMaximum));
|
||||
activeTargets.Add(new MapTargetNetworkState(
|
||||
nextTargetId++, configIndex, coordinates,
|
||||
config.Health, config.TimeBeforeAttack));
|
||||
initialTargetCount++;
|
||||
}
|
||||
|
||||
Debug.Log($"[Map] Wave {currentWave.Value} started with {initialTargetCount} targets.", this);
|
||||
if (initialTargetCount == 0)
|
||||
CompleteWaveOnServer();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SimulateTargets(float deltaTime)
|
||||
{
|
||||
for (int index = activeTargets.Count - 1; index >= 0; index--)
|
||||
{
|
||||
MapTargetNetworkState state = activeTargets[index];
|
||||
TargetConfig config = targetController.GetConfig(state.ConfigIndex);
|
||||
if (config == null)
|
||||
{
|
||||
ResolveEscapedTarget(index, state, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isAirTarget = config.TargetPrefab is AirTarget;
|
||||
if (isAirTarget && mapPlayer != null && config.MovementSpeed > 0f)
|
||||
{
|
||||
Vector2 destination = mapPlayer.MapCoordinates;
|
||||
state.Coordinates = Vector2.MoveTowards(
|
||||
state.Coordinates, destination, config.MovementSpeed * deltaTime);
|
||||
if (Vector2.Distance(state.Coordinates, destination) <= config.StoppingDistance)
|
||||
{
|
||||
ResolveEscapedTarget(index, state, config);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state.AttackTimeRemaining = Mathf.Max(
|
||||
0f, state.AttackTimeRemaining - deltaTime);
|
||||
if (state.AttackTimeRemaining <= 0f)
|
||||
{
|
||||
ResolveEscapedTarget(index, state, config);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
activeTargets[index] = state;
|
||||
}
|
||||
|
||||
TryCompleteWaveOnServer();
|
||||
}
|
||||
|
||||
private void ResolveEscapedTarget(int index, MapTargetNetworkState target, TargetConfig config)
|
||||
{
|
||||
int damage = config != null ? config.BaseDamage : 1;
|
||||
escapedTargetCount++;
|
||||
activeTargets.RemoveAt(index);
|
||||
if (baseHealth != null)
|
||||
baseHealth.ApplyDamage(damage);
|
||||
Debug.Log($"[Map] Target {target.TargetId} reached the base. Base damage: {damage}.", this);
|
||||
}
|
||||
|
||||
private void ResolvePseudoShotOnServer()
|
||||
{
|
||||
if (!IsServer || !waveIsActive)
|
||||
{
|
||||
PublishShotResult(false, -1, -1f);
|
||||
return;
|
||||
}
|
||||
|
||||
int nearestIndex = -1;
|
||||
float nearestDistance = float.PositiveInfinity;
|
||||
for (int index = 0; index < activeTargets.Count; index++)
|
||||
{
|
||||
float distance = Vector2.Distance(
|
||||
crosshairCoordinates.Value, activeTargets[index].Coordinates);
|
||||
if (distance >= nearestDistance)
|
||||
continue;
|
||||
nearestDistance = distance;
|
||||
nearestIndex = index;
|
||||
}
|
||||
|
||||
if (nearestIndex >= 0 && nearestDistance <= hitRadius)
|
||||
{
|
||||
MapTargetNetworkState target = activeTargets[nearestIndex];
|
||||
TargetConfig config = targetController.GetConfig(target.ConfigIndex);
|
||||
bool missileMatches = ignoreMissileTypeForPrototype || config == null ||
|
||||
config.RequiredMissileType == MissileType.None ||
|
||||
config.RequiredMissileType == pseudoMissileType;
|
||||
if (missileMatches)
|
||||
{
|
||||
target.Health -= shotDamage;
|
||||
if (target.Health <= 0)
|
||||
activeTargets.RemoveAt(nearestIndex);
|
||||
else
|
||||
activeTargets[nearestIndex] = target;
|
||||
|
||||
PublishShotResult(true, target.TargetId, nearestDistance);
|
||||
Debug.Log($"[Map] HIT target {target.TargetId} at {nearestDistance:0.00} map units.", this);
|
||||
TryCompleteWaveOnServer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int missedTargetId = nearestIndex >= 0 ? activeTargets[nearestIndex].TargetId : -1;
|
||||
PublishShotResult(false, missedTargetId, nearestDistance);
|
||||
float printedDistance = float.IsPositiveInfinity(nearestDistance) ? -1f : nearestDistance;
|
||||
Debug.Log($"[Map] MISS at {crosshairCoordinates.Value}. Nearest distance: {printedDistance:0.00}.", this);
|
||||
}
|
||||
|
||||
private void PublishShotResult(bool hit, int targetId, float distance)
|
||||
{
|
||||
lastShotResult.Value = new MapShotResultState(
|
||||
lastShotResult.Value.Sequence + 1, hit, targetId,
|
||||
crosshairCoordinates.Value,
|
||||
float.IsPositiveInfinity(distance) ? -1f : distance);
|
||||
}
|
||||
|
||||
private void ScanRadarOnServer()
|
||||
{
|
||||
if (!IsServer || radarController == null || NetworkManager == null ||
|
||||
NetworkManager.ServerTime.Time < radarReadyAt.Value)
|
||||
return;
|
||||
|
||||
radarMarks.Clear();
|
||||
foreach (MapTargetNetworkState target in activeTargets)
|
||||
radarMarks.Add(target.Coordinates);
|
||||
radarReadyAt.Value = NetworkManager.ServerTime.Time + radarController.Cooldown;
|
||||
Debug.Log($"[Map] Radar scan found {radarMarks.Count} targets.", this);
|
||||
}
|
||||
|
||||
private void TryCompleteWaveOnServer()
|
||||
{
|
||||
if (waveIsActive && activeTargets.Count == 0)
|
||||
CompleteWaveOnServer();
|
||||
}
|
||||
|
||||
private void CompleteWaveOnServer()
|
||||
{
|
||||
waveIsActive = false;
|
||||
resolvedSequence.Value++;
|
||||
if (initialTargetCount > 0 && escapedTargetCount == 0)
|
||||
destroyedSequence.Value++;
|
||||
Debug.Log(
|
||||
$"[Map] Wave {currentWave.Value} resolved. " +
|
||||
$"Destroyed: {Mathf.Max(0, initialTargetCount - escapedTargetCount)}, " +
|
||||
$"escaped: {escapedTargetCount}.", this);
|
||||
}
|
||||
|
||||
private void ConfigurePresentation()
|
||||
{
|
||||
mapPlayer?.Configure(coordinateSystem);
|
||||
targetController?.Configure(coordinateSystem, targetParent, mapPlayer);
|
||||
radarController?.Configure(coordinateSystem, radarMarkPrefab);
|
||||
crosshair?.Configure(
|
||||
coordinateSystem, relayX, relayY, crosshairVisual, targetController);
|
||||
}
|
||||
|
||||
private void ApplyPresentation()
|
||||
{
|
||||
crosshair?.SetCoordinates(crosshairCoordinates.Value);
|
||||
targetController?.ApplyNetworkTargets(CreateTargetSnapshot(), currentWave.Value);
|
||||
radarController?.ApplyRadarMarks(CreateRadarSnapshot());
|
||||
if (radarController != null)
|
||||
radarController.SetCooldownRemaining((float)RadarCooldownRemaining);
|
||||
}
|
||||
|
||||
private void BindRoundEvents()
|
||||
{
|
||||
if (roundEventsBound)
|
||||
return;
|
||||
if (roundGameLoop == null)
|
||||
roundGameLoop = FindFirstObjectByType<RoundGameLoopController>();
|
||||
if (roundGameLoop == null || !roundGameLoop.IsSpawned)
|
||||
return;
|
||||
roundGameLoop.PhaseChanged += HandleRoundPhaseChanged;
|
||||
roundEventsBound = true;
|
||||
}
|
||||
|
||||
private void UnbindRoundEvents()
|
||||
{
|
||||
if (!roundEventsBound || roundGameLoop == null)
|
||||
return;
|
||||
roundGameLoop.PhaseChanged -= HandleRoundPhaseChanged;
|
||||
roundEventsBound = false;
|
||||
}
|
||||
|
||||
private void HandleRoundPhaseChanged(RoundPhase phase)
|
||||
{
|
||||
if (IsServer && phase == RoundPhase.WorkInProgress && !waveIsActive)
|
||||
StartNextWaveOnServer();
|
||||
}
|
||||
|
||||
private void HandleTargetListChanged(NetworkListEvent<MapTargetNetworkState> _) =>
|
||||
targetController?.ApplyNetworkTargets(CreateTargetSnapshot(), currentWave.Value);
|
||||
private void HandleRadarListChanged(NetworkListEvent<Vector2> _) =>
|
||||
radarController?.ApplyRadarMarks(CreateRadarSnapshot());
|
||||
private void HandleCrosshairChanged(Vector2 _, Vector2 current) =>
|
||||
crosshair?.SetCoordinates(current);
|
||||
|
||||
private void HandleWaveChanged(int _, int current)
|
||||
{
|
||||
targetController?.ApplyNetworkTargets(CreateTargetSnapshot(), current);
|
||||
WaveStarted?.Invoke(current);
|
||||
waveStarted?.Invoke(current);
|
||||
}
|
||||
|
||||
private void HandleRadarReadyAtChanged(double _, double __)
|
||||
{
|
||||
if (radarController != null)
|
||||
radarController.SetCooldownRemaining((float)RadarCooldownRemaining);
|
||||
}
|
||||
|
||||
private void HandleShotResultChanged(MapShotResultState previous, MapShotResultState current)
|
||||
{
|
||||
if (current.Sequence == 0 || current.Sequence == previous.Sequence)
|
||||
return;
|
||||
ShotResolved?.Invoke(current);
|
||||
shotResolved?.Invoke(current.Hit);
|
||||
}
|
||||
|
||||
private void HandleResolvedSequenceChanged(uint previous, uint current)
|
||||
{
|
||||
if (current == previous)
|
||||
return;
|
||||
AllTargetsResolved?.Invoke();
|
||||
allTargetsResolved?.Invoke();
|
||||
}
|
||||
|
||||
private void HandleDestroyedSequenceChanged(uint previous, uint current)
|
||||
{
|
||||
if (current == previous)
|
||||
return;
|
||||
AllTargetsDestroyed?.Invoke();
|
||||
allTargetsDestroyed?.Invoke();
|
||||
}
|
||||
|
||||
private MapTargetNetworkState[] CreateTargetSnapshot()
|
||||
{
|
||||
MapTargetNetworkState[] snapshot = new MapTargetNetworkState[activeTargets.Count];
|
||||
for (int index = 0; index < snapshot.Length; index++)
|
||||
snapshot[index] = activeTargets[index];
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
private Vector2[] CreateRadarSnapshot()
|
||||
{
|
||||
Vector2[] snapshot = new Vector2[radarMarks.Count];
|
||||
for (int index = 0; index < snapshot.Length; index++)
|
||||
snapshot[index] = radarMarks[index];
|
||||
return snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user