145 lines
4.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|