using Cysharp.Threading.Tasks; using RR.UI; using System; using System.Collections.Generic; using System.Threading; using TMPro; using UnityEngine; using UnityEngine.UI; public class AwardsController2 : MonoBehaviour { [Header("Boot")] [SerializeField] private Canvas canvas; [SerializeField] private Canvas vrCanvas; [SerializeField] private float timeout = 120; [SerializeField] private string menuSceneName = "MenuOneRegime"; [SerializeField] private string gameplaySceneName = "Gameplay"; [Header("Линии и заголовок")] [SerializeField] private RectTransform linesLayout; [SerializeField] private float startLinesX = -1920, targetLinesX = 0; [SerializeField] private AnimationCurve linesCurve; [Header("Счетчики")] [SerializeField] private List shipCounters; [SerializeField] private List shipCountersVR; // [SerializeField] private CanvasGroup destroyedEnemiesCG; [SerializeField] private CanvasGroup destroyedEnemiesVR; [SerializeField] AudioClip soundExplosion; [SerializeField] AudioClip soundShoot; [Header("Счет")] [SerializeField] private CanvasGroup scoreCG; [SerializeField] private CanvasGroup scoreVR; [SerializeField] private CounterTMP scoreCounter; [SerializeField] private CounterTMP scoreCounterVR; [Header("Ранг")] [SerializeField] private CanvasGroup rankPanelCG; [SerializeField] private CanvasGroup rankPanelVR; [SerializeField] private CanvasGroup rankViewCG; [SerializeField] private CanvasGroup rankViewVR; [SerializeField] private CanvasGroup ranksTableCG; [SerializeField] private Image rankImage; [SerializeField] private Image rankImageVR; [SerializeField] private TextMeshProUGUI rankLabel; [SerializeField] private TextMeshProUGUI rankLabelVR; [SerializeField] private List rankViews; [Header("До след ранга")] [SerializeField] private CanvasGroup ToNextRankCG; [SerializeField] private TextMeshProUGUI ToNextRankScore; private bool shouldEnableToNextRank = false; [Header("Инфо панель")] [SerializeField] private CanvasGroup InfoPanelCG; [SerializeField] TextMeshProUGUI timerLabel; [SerializeField] TextMeshProUGUI balanceLabel; [SerializeField] TextMeshProUGUI continueLabel; [SerializeField] private CanvasGroup ExitCG; [SerializeField] private CanvasGroup ContinueCG; [SerializeField] InputController inputController; private CancellationTokenSource cts; private bool Freeplay => SettingsManager.GetBool(SettingKey.Freeplay, false); private int PriceContinue => SettingsManager.GetInt(SettingKey.RevengePrice, 10); [SerializeField] Image BgImage; [SerializeField] private Sprite goodBg; [SerializeField] private Sprite badBg; [SerializeField] AudioSource scoreSound; private void Start() { if (!BootstrapperState.MainBootstraped) { SceneLoader.LoadScene("Bootstrap"); return; } Init(); cts = new(); var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, GameManager.globalCts.Token); Process(linkedCts.Token).Forget(); } private void OnApplicationQuit() { cts?.Cancel(); cts?.Dispose(); } private void Init() { SetBackgroundByReason(G.EndGameChecker.lastReason); destroyedEnemiesCG.alpha = 0; destroyedEnemiesVR.alpha = 0; //инит счетчики foreach (var shipCounter in shipCounters) { shipCounter.SetAlpha(0); shipCounter.ShowScore(G.ScoreModel); } foreach (var shipCounter in shipCountersVR) { shipCounter.SetAlpha(0); shipCounter.ShowScore(G.ScoreModel); } scoreCG.alpha = 0; scoreVR.alpha = 0; scoreCounter.SetCount(0); scoreCounterVR.SetCount(0); rankPanelCG.alpha = 0; rankPanelVR.alpha = 0; rankViewCG.alpha = 0; rankViewVR.alpha = 0; rankImage.sprite = G.Rank.SpriteGreen; rankImageVR.sprite = G.Rank.SpriteGreen; rankLabel.text = G.Rank.Name; rankLabelVR.text = G.Rank.Name; //до след ранга shouldEnableToNextRank = RankSystem.Instance.HasNextRank(G.ScoreModel.Score); if (shouldEnableToNextRank) { ToNextRankScore.text = RankSystem.Instance.ScoreToNextRank(G.ScoreModel.Score).ToString() + " очков"; } ToNextRankCG.alpha = 0; //ини таблицы рангов ranksTableCG.alpha = 0; int actualRankIndex = RankSystem.Instance.GetActualRankIndex(G.ScoreModel.Score); for (int i = 0; i < rankViews.Count; i++) { RankSystem.RankInfo rankInfo = RankSystem.Instance.Ranks[i]; float alpha = i > actualRankIndex ? 0.2f : 1f; bool enableFrame = i == actualRankIndex; rankViews[i].Configure(alpha, enableFrame, rankInfo.Name, rankInfo.RequiredScore, rankInfo.SpriteGreen); } InfoPanelCG.alpha = 0; canvas.worldCamera = CamerasManager.Screen_Camera; vrCanvas.worldCamera = CamerasManager.VR_Camera; } private void SetBackgroundByReason(EndGameConditionChecker.EndgameReason reason) { if (reason == EndGameConditionChecker.EndgameReason.Death) BgImage.sprite = badBg; else BgImage.sprite = goodBg; } private async UniTask Process(CancellationToken ct) { await ShowLinesAndTitle(1, ct); await ShowDestroyedEnemies(ct); await ShowScore(ct); await ShowRank(ct); await UniTask.Delay(2000, cancellationToken: ct); if(shouldEnableToNextRank) LerpAlpha(0, 1,1, ToNextRankCG, ct).Forget(); RanksAndDestroyedAnimation(ct).Forget(); InstructionsAnimation(ct).Forget(); InitInfoPanel(); await LerpAlpha(0, 1, 1, InfoPanelCG, ct); ActivateControls(); StartExitByTimerProcess(ct).Forget(); } private async UniTask ShowLinesAndTitle(float duration, CancellationToken ct) { float elapsed = 0; while (!ct.IsCancellationRequested && elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Min(1, elapsed / duration); float t1 = linesCurve.Evaluate(t); float x = Mathf.Lerp(startLinesX, targetLinesX, t1); linesLayout.anchoredPosition = new Vector2(x, linesLayout.localPosition.y); await UniTask.Yield(ct); } if (!ct.IsCancellationRequested) { linesLayout.anchoredPosition = new Vector2(targetLinesX, linesLayout.localPosition.y); } } private async UniTask ShowDestroyedEnemies(CancellationToken ct) { SoundManager.PlayUi(soundExplosion); destroyedEnemiesCG.alpha = 1; destroyedEnemiesVR.alpha = 1; for (int i = 0; i < shipCounters.Count; i++) { await UniTask.Delay(500, cancellationToken: ct); SoundManager.PlayUi(soundShoot); shipCounters[i].SetAlpha(1); shipCountersVR[i].SetAlpha(1); } } private async UniTask ShowScore(CancellationToken ct) { LerpAlpha(0, 1, 5, scoreVR, ct).Forget(); await LerpAlpha(0, 1, 5, scoreCG, ct); await UniTask.Delay(1000, cancellationToken: ct); scoreSound.Play(); scoreCounterVR.AnimateScoreChange(0, G.ScoreModel.Score).Forget(); await scoreCounter.AnimateScoreChange(0, G.ScoreModel.Score); scoreSound.Stop(); } private async UniTask ShowRank(CancellationToken ct) { LerpAlpha(0, 1, 5, rankPanelVR, ct).Forget(); await LerpAlpha(0, 1, 5, rankPanelCG, ct); await UniTask.Delay(1000, cancellationToken: ct); SoundManager.PlayUi(soundShoot); rankViewCG.alpha = 1; rankViewVR.alpha = 1; } private async UniTask RanksAndDestroyedAnimation(CancellationToken ct) { var descendingGroup = destroyedEnemiesCG; var ascendingGroup = ranksTableCG; while (!ct.IsCancellationRequested) { await LerpAlpha(1, 0, 1, descendingGroup, ct); await LerpAlpha(0, 1, 1, ascendingGroup, ct); await UniTask.Delay(3000, cancellationToken: ct); if (!ct.IsCancellationRequested) { (descendingGroup, ascendingGroup) = (ascendingGroup, descendingGroup); } } } private async UniTask InstructionsAnimation(CancellationToken ct) { var descendingGroup = ContinueCG; var ascendingGroup = ExitCG; while (!ct.IsCancellationRequested) { await LerpAlpha(1, 0, 1, descendingGroup, ct); await LerpAlpha(0, 1, 1, ascendingGroup, ct); await UniTask.Delay(3000, cancellationToken: ct); if (!ct.IsCancellationRequested) { (descendingGroup, ascendingGroup) = (ascendingGroup, descendingGroup); } } } private void ActivateControls() { inputController.Init(startPolling: true); } public void InitInfoPanel() { UpdateTimer(timeout); UpdateBalance(WalletManager.Balance); WalletManager.OnBalanceChanged += UpdateBalance; balanceLabel.enabled = !Freeplay; if (Freeplay) { continueLabel.text = $"Продолжить\n "; } else { int price = PriceContinue; continueLabel.text = $"Продолжить\n{price} {GetValutaPluralized(price)}"; } } private async UniTask StartExitByTimerProcess(CancellationToken ct) { while(timeout > 0 && !ct.IsCancellationRequested) { UpdateTimer(timeout); timeout -= 1; await UniTask.Delay(1000, cancellationToken:ct); } if(!ct.IsCancellationRequested) { ExitMenu(); } } public void ExitMenu() { cts?.Cancel(); cts?.Dispose(); cts = null; WalletManager.OnBalanceChanged -= UpdateBalance; SceneLoader.LoadScene(menuSceneName); } public void Resume() { if(Freeplay || WalletManager.TryTakeMoney(PriceContinue)) { cts?.Cancel(); cts?.Dispose(); cts = null; WalletManager.OnBalanceChanged -= UpdateBalance; SceneLoader.LoadScene(gameplaySceneName); } } //Helpers private async UniTask LerpAlpha(float from, float to, float speed, CanvasGroup cg, CancellationToken ct) { float t = 0; while (t < 1 && !ct.IsCancellationRequested) { t += Time.deltaTime * speed; t = Mathf.Min(t, 1); cg.alpha = Mathf.Lerp(from, to, t); await UniTask.Yield(ct); } cg.alpha = to; } private string GetValutaPluralized(int balance) => SettingsManager.GetString(SettingKey.Valuta, "руб.") == "руб." ? PluralizeUtil.Rubles(balance) : PluralizeUtil.Tokens(balance); private void UpdateTimer(float timerest) { TimeSpan time = TimeSpan.FromSeconds(timerest); timerLabel.text = $"выход в меню через:\n {time.ToString(@"mm\:ss")}"; } private void UpdateBalance(int balance) { balanceLabel.text = $"баланс:\n{balance} {GetValutaPluralized(WalletManager.Balance)}"; } }