geometry-tower-defense/Assets/GameMain/Scripts/CustomComponent/CombatNode/PhaseLoopRuntime.cs

145 lines
4.2 KiB
C#

using System.Collections.Generic;
using System.Globalization;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.CustomComponent
{
internal sealed class PhaseLoopRuntime
{
private readonly List<DRLevelPhase> _phases = new();
private DRLevelPhase _currentPhase;
private int _currentPhaseIndex = -1;
private int _displayPhaseIndex;
private int _completedLoopCount;
private bool _canEndCombat;
private bool _endCombatRequested;
private float _currentPhaseElapsed;
public DRLevelPhase CurrentPhase => _currentPhase;
public int DisplayPhaseIndex => _displayPhaseIndex;
public bool CanEndCombat => _canEndCombat;
public float CurrentPhaseElapsed => _currentPhaseElapsed;
public int PhaseCount => _phases.Count;
public void Reset()
{
_phases.Clear();
_currentPhase = null;
_currentPhaseIndex = -1;
_displayPhaseIndex = 0;
_completedLoopCount = 0;
_canEndCombat = false;
_endCombatRequested = false;
_currentPhaseElapsed = 0f;
}
public void SetPhases(IReadOnlyList<DRLevelPhase> phases)
{
_phases.Clear();
if (phases == null)
{
return;
}
for (int i = 0; i < phases.Count; i++)
{
DRLevelPhase phase = phases[i];
if (phase != null)
{
_phases.Add(phase);
}
}
}
public bool TryRequestEndCombat()
{
if (!_canEndCombat)
{
return false;
}
_endCombatRequested = true;
return true;
}
public void AdvancePhaseElapsed(float elapseSeconds)
{
_currentPhaseElapsed += elapseSeconds;
}
public bool ShouldEndCurrentPhase(bool isPhaseSpawnCompleted, int aliveEnemyCount)
{
if (_currentPhase == null)
{
return false;
}
switch (_currentPhase.EndType)
{
case PhaseEndType.TimeElapsed:
return _currentPhaseElapsed >= ResolveTimeElapsedThreshold(_currentPhase);
case PhaseEndType.EnemiesCleared:
case PhaseEndType.BossDead:
return isPhaseSpawnCompleted && aliveEnemyCount <= 0;
case PhaseEndType.None:
default:
if (_currentPhase.DurationSeconds > 0 && _currentPhaseElapsed >= _currentPhase.DurationSeconds)
{
return true;
}
return isPhaseSpawnCompleted && aliveEnemyCount <= 0;
}
}
public bool TryEnterNextPhase(out DRLevelPhase nextPhase)
{
nextPhase = null;
if (_phases.Count <= 0)
{
return false;
}
_currentPhaseIndex++;
if (_currentPhaseIndex >= _phases.Count)
{
_completedLoopCount++;
_canEndCombat = true;
if (_endCombatRequested)
{
_currentPhase = null;
return false;
}
_currentPhaseIndex = 0;
}
_currentPhase = _phases[_currentPhaseIndex];
_displayPhaseIndex = _completedLoopCount * _phases.Count + _currentPhaseIndex + 1;
_currentPhaseElapsed = 0f;
nextPhase = _currentPhase;
return true;
}
private static float ResolveTimeElapsedThreshold(DRLevelPhase phase)
{
if (!string.IsNullOrWhiteSpace(phase.EndParam) &&
float.TryParse(phase.EndParam, NumberStyles.Float, CultureInfo.InvariantCulture, out float parsed))
{
return parsed;
}
if (phase.DurationSeconds > 0)
{
return phase.DurationSeconds;
}
return 0f;
}
}
}