using System.Collections.Generic; using UnityEngine; using Zenject; namespace DanroJump.Gameplay { public sealed class GameplayDifficultyProgression : MonoBehaviour, IGameplayDifficultyProgression { [SerializeField] private JumpPlayerController player; [SerializeField] private bool progressionEnabled = true; [SerializeField] private List stages = new(); public bool HasStages => stages != null && stages.Exists(stage => stage != null); public float InitialSpawnY => GetInitialSpawnY(); public float CurrentProgress => CalculateProgress(player != null ? player.HighestY : 0f); public string CurrentStageName => GetStage(player != null ? player.HighestY : 0f)?.StageName ?? string.Empty; [Inject] public void Construct(JumpPlayerController injectedPlayer) { player = injectedPlayer; } public GameObject GetPlatformPrefab(float worldY, System.Random random) { var stage = GetStage(worldY); return stage != null ? stage.GetPlatformPrefab(random) : null; } public float GetVerticalSpacing(float worldY) { var stage = GetStage(worldY); if (stage == null) { return 0f; } return stage.GetVerticalSpacing(worldY); } public float GetHorizontalDistribution(float worldY) { var stage = GetStage(worldY); return stage != null ? stage.GetHorizontalDistribution() : 0f; } public IPlatformContentSource CreateContentSource(float worldY) { var stage = GetStage(worldY); if (stage == null) { return null; } return stage.CreateContentSource(worldY); } public string GetStageName(float worldY) { return GetStage(worldY)?.StageName ?? string.Empty; } public float GetStageProgress(float worldY) { var stage = GetStage(worldY); return stage != null ? stage.CalculateProgress(worldY) : 0f; } private float CalculateProgress(float worldY) { var stage = GetStage(worldY); return stage != null ? stage.CalculateProgress(worldY) : 0f; } private float GetInitialSpawnY() { var firstStage = GetFirstStage(); return firstStage != null ? firstStage.StartY : 0f; } private GameplayDifficultyStage GetFirstStage() { if (stages == null || stages.Count == 0) { return null; } GameplayDifficultyStage firstStage = null; foreach (var stage in stages) { if (stage == null) { continue; } if (firstStage == null || stage.StartY < firstStage.StartY) { firstStage = stage; } } return firstStage; } private GameplayDifficultyStage GetStage(float worldY) { if (!progressionEnabled || stages == null || stages.Count == 0) { return null; } GameplayDifficultyStage currentStage = null; foreach (var stage in stages) { if (stage == null || worldY < stage.StartY) { continue; } if (currentStage == null || stage.StartY >= currentStage.StartY) { currentStage = stage; } } // The last reached stage intentionally keeps running forever after its length ends. // verticalLength controls curve progress only; it does not disable the stage. return currentStage; } } public interface IGameplayDifficultyProgression { float CurrentProgress { get; } string CurrentStageName { get; } bool HasStages { get; } float InitialSpawnY { get; } GameObject GetPlatformPrefab(float worldY, System.Random random); float GetVerticalSpacing(float worldY); float GetHorizontalDistribution(float worldY); IPlatformContentSource CreateContentSource(float worldY); string GetStageName(float worldY); float GetStageProgress(float worldY); } }