using UnityEngine; using DG.Tweening; using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine.Networking; using UnityEngine.UI; public class GameOverCanvas : MonoBehaviour { public bool showOnLoad = false; CanvasGroup canvasGroup; [Header("Intro items")] public RectTransform[] middleScalingItems; public RectTransform[] comingFromMiddle; public RectTransform[] prizeFrames; public RectTransform[] comingDown; Dictionary OriginalPositions; Dictionary OriginalScales; [Header("Values")] public TMP_Text p1_name; public TMP_Text p1_l10; public TMP_Text p2_name; public TMP_Text p2_l10; public GameObject p1_red,p2_red,p1_blue,p2_blue; public Image p1_icon, p2_icon; public Sprite redIcon, blueIcon; public RectTransform p1_winner, p2_winner; [Header("Game Over Data")] public Button btnRematch; public Button btnLeave; public GameObject rematchWarningLoser; public TMP_Text txtRewardRC; public TMP_Text txtRewardCC; public TMP_Text countdownTxt; string returningToMenuText; public float returnToMenuCountdown = 15f; [Header("Rematch panel")] public CanvasGroup rematchPanel; public RectTransform rematchPopup; public TMP_Text txtMyRCBalance, txtOpponentRCBalance; public TMP_Text txtSelectedBet; public Slider betSlider; public Button btnConfirmBet; public Button btnCancelBet; public static GameOverCanvas instance; void Awake() { instance = this; canvasGroup = GetComponent(); Hide(); CollectOriginalPositionsAndScales(); returningToMenuText = countdownTxt.text; } void Start() { if(showOnLoad){ if(LevelLoadManager.instance == null){ //Load dummy data for testing LevelLoadManager.myPlayer = new MatchmadePlayer(){Name = "test p1", l10_wins = 3, l10_losses = 1}; LevelLoadManager.opponentPlayer = new MatchmadePlayer(){Name = "test p2", l10_wins = 1, l10_losses = 3}; } Show(Team.Red, Team.Red, 3, 1); } btnRematch.onClick.AddListener(OnBtnRematchClicked); btnLeave.onClick.AddListener(OnBtnLeaveGameClicked); betSlider.onValueChanged.AddListener(OnBetSliderValueChanged); } void OnBetSliderValueChanged(float value){ txtSelectedBet.text = CoinHelper.FormatString((int)value); } void OnBtnRematchClicked(){ // LevelLoadManager.LoadLevel("Game"); NetPlayer.localPlayer.RequestRematch(); SetRematchPendingState(true); } public void OnRematchRequested(){ if(winningTeam == myTeam){ //Only i can initiate the rematch, so here we go ShowRematchPanel(); } } void SetRematchPendingState(bool val){ btnRematch.interactable = false; btnLeave.interactable = !val; if(val){ StopCoroutine(countdownCoroutine); }else{ countdownCoroutine = StartCoroutine(CoroutineCountdown()); } } void OnBtnLeaveGameClicked(){ LevelLoadManager.LoadLevel("MainMenu"); } void CollectOriginalPositionsAndScales(){ OriginalPositions = new Dictionary(); OriginalScales = new Dictionary(); foreach (var item in comingFromMiddle) { OriginalPositions.Add(item, item.position); OriginalScales.Add(item, item.localScale); } foreach (var item in middleScalingItems) { if(!OriginalPositions.ContainsKey(item)){ OriginalPositions.Add(item, item.position); } if(!OriginalScales.ContainsKey(item)){ OriginalScales.Add(item, item.localScale); } } foreach (var item in comingDown) { if(!OriginalPositions.ContainsKey(item)){ OriginalPositions.Add(item, item.position); } if(!OriginalScales.ContainsKey(item)){ OriginalScales.Add(item, item.localScale); } } foreach (var item in prizeFrames) { if(!OriginalPositions.ContainsKey(item)){ OriginalPositions.Add(item, item.position); } if(!OriginalScales.ContainsKey(item)){ OriginalScales.Add(item, item.localScale); } } } void Hide(){ canvasGroup.alpha = 0; canvasGroup.blocksRaycasts = false; canvasGroup.interactable = false; rematchPanel.alpha=0; rematchPanel.blocksRaycasts = false; rematchPanel.interactable = false; } Team winningTeam; Team myTeam; public void Setup(Team winningTeam, Team myTeam, int redScore, int blueScore){ this.winningTeam = winningTeam; this.myTeam = myTeam; p1_winner.gameObject.SetActive(false); p2_winner.gameObject.SetActive(false); if(myTeam == Team.Red){ p1_red.SetActive(true); p1_blue.SetActive(false); p2_red.SetActive(false); p2_blue.SetActive(true); p1_icon.sprite = redIcon; p2_icon.sprite = blueIcon; }else{ p1_red.SetActive(false); p1_blue.SetActive(true); p2_red.SetActive(true); p2_blue.SetActive(false); p1_icon.sprite = blueIcon; p2_icon.sprite = redIcon; } p1_name.text = LevelLoadManager.myPlayer.Name; p2_name.text = LevelLoadManager.opponentPlayer.Name; p1_l10.text = $"L10 {LevelLoadManager.myPlayer.l10_wins}-{LevelLoadManager.myPlayer.l10_losses}"; p2_l10.text = $"L10 {LevelLoadManager.opponentPlayer.l10_wins}-{LevelLoadManager.opponentPlayer.l10_losses}"; if(myTeam == winningTeam){ p1_winner.gameObject.SetActive(true); p2_winner.gameObject.SetActive(false); }else{ p1_winner.gameObject.SetActive(false); p2_winner.gameObject.SetActive(true); } } float rcPrize = 0; public void Show(Team winningTeam, Team myTeam, int redScore, int blueScore){ Setup(winningTeam, myTeam, redScore, blueScore); canvasGroup.blocksRaycasts = true; canvasGroup.interactable = true; foreach (var item in middleScalingItems) { item.localScale = new Vector3(0, item.localScale.y, item.localScale.z); } foreach (var item in comingFromMiddle) { item.position = new Vector3(Screen.width/2f,OriginalPositions[item].y); item.localScale = new Vector3(0, OriginalScales[item].y, OriginalScales[item].z); } foreach (var item in comingDown) { item.position = new Vector3(OriginalPositions[item].x, 0.3f); item.localScale = new Vector3(OriginalScales[item].x, 0, OriginalScales[item].z); } foreach (var item in prizeFrames) { item.localScale = new Vector3(0, 0, 0); } if(winningTeam == myTeam){ rcPrize = 8.2f; } btnRematch.interactable = winningTeam != myTeam; rematchWarningLoser.SetActive(winningTeam == myTeam); StartCoroutine(CoroutineShow()); StartCoroutine(CoroutineFetchAndUpdateBalances()); } IEnumerator CoroutineShow(){ float fadeInTime = 0.5f; float scaleTime = 0.2f; float moveTime = 0.3f; canvasGroup.DOFade(1, fadeInTime).SetEase(Ease.InOutBack); yield return new WaitForSeconds(fadeInTime); foreach (var item in middleScalingItems) { item.DOScale(OriginalScales[item], scaleTime).SetEase(Ease.InOutBack); } yield return new WaitForSeconds(scaleTime * 0.5f); foreach (var item in comingFromMiddle) { item.DOMove(OriginalPositions[item], moveTime).SetEase(Ease.InOutBack); item.DOScale(OriginalScales[item], scaleTime).SetEase(Ease.InOutBack); } yield return new WaitForSeconds(scaleTime * 0.5f); foreach (var item in prizeFrames) { item.DOScale(Vector3.one, scaleTime).SetEase(Ease.InOutBack); } yield return new WaitForSeconds(scaleTime * 0.5f); //Rewards StartCoroutine(CoroutineSetTextNumber(rcPrize, txtRewardRC, 10, "N1", "+", " RC")); StartCoroutine(CoroutineSetTextNumber(100, txtRewardCC, 100, "N0", "+", " CC")); yield return new WaitForSeconds(1f); foreach (var item in comingDown) { item.DOMove(OriginalPositions[item], 0.3f).SetEase(Ease.InOutBack); item.DOScale(OriginalScales[item], 0.3f).SetEase(Ease.InOutBack); } countdownCoroutine = StartCoroutine(CoroutineCountdown()); } Coroutine countdownCoroutine; IEnumerator CoroutineSetTextNumber(float number, TMP_Text text, float speed = 100f, string formatting = "N0", string prefix = "", string suffix = ""){ float t=0; while(t < number){ t+=Time.deltaTime*speed; text.text = prefix + t.ToString(formatting) + suffix; yield return null; } text.text = prefix + number.ToString(formatting) + suffix; } IEnumerator CoroutineCountdown(){ TextColorFlash textColorFlash = countdownTxt.GetComponent(); while(returnToMenuCountdown > 0){ returnToMenuCountdown--; countdownTxt.text = returningToMenuText.Replace("{t}", returnToMenuCountdown.ToString("N0")); if(returnToMenuCountdown < 5){ textColorFlash.duration = 5; } yield return new WaitForSecondsRealtime(1f); } LevelLoadManager.LoadLevel("MainMenu"); } public void ShowRematchPanel(){ SetRematchPendingState(true); StartCoroutine(CoroutineShowRematchPanel()); betSlider.maxValue = (LevelLoadManager.myPlayer.rc < LevelLoadManager.opponentPlayer.rc) ? LevelLoadManager.myPlayer.rc : LevelLoadManager.opponentPlayer.rc; } IEnumerator CoroutineShowRematchPanel(){ rematchPopup.localScale = new Vector3(0, 0, 0); rematchPanel.blocksRaycasts = true; rematchPanel.interactable = true; rematchPanel.DOFade(1, 0.3f).SetEase(Ease.InOutBack); yield return new WaitForSeconds(0.1f); rematchPopup.DOScale(1, 0.2f).SetEase(Ease.OutBack); yield return new WaitForSeconds(0.2f); } public void OnRematchCancelled(){ SetRematchPendingState(false); StartCoroutine(CoroutineHideRematchPanel()); } IEnumerator CoroutineHideRematchPanel(){ rematchPopup.DOScale(0, 0.2f).SetEase(Ease.InBack); yield return new WaitForSeconds(0.2f); rematchPanel.DOFade(0, 0.3f).SetEase(Ease.InOutBack); yield return new WaitForSeconds(0.3f); } IEnumerator CoroutineFetchAndUpdateBalances() { var my = LevelLoadManager.myPlayer; var opp = LevelLoadManager.opponentPlayer; string baseUrl = (GameManager.DedicatedInternalApiBase ?? "").TrimEnd('/'); if (string.IsNullOrEmpty(baseUrl) || my == null || opp == null) { ApplyRcBalancesToUi(null); yield break; } if (my.UserId > 0) yield return FetchPlayerRcAndApply(baseUrl, my); if (opp.UserId > 0 && opp.UserId != my.UserId) yield return FetchPlayerRcAndApply(baseUrl, opp); ApplyRcBalancesToUi(null); } void ApplyRcBalancesToUi(string loadingPlaceholder) { var my = LevelLoadManager.myPlayer; var opp = LevelLoadManager.opponentPlayer; string myText = loadingPlaceholder ?? (my != null ? CoinHelper.FormatString((int)my.rc) : "0.0 RC"); string oppText = loadingPlaceholder ?? (opp != null ? CoinHelper.FormatString((int)opp.rc) : "0.0 RC"); if (txtMyRCBalance != null) txtMyRCBalance.text = myText; if (txtOpponentRCBalance != null) txtOpponentRCBalance.text = oppText; } IEnumerator FetchPlayerRcAndApply(string baseUrl, MatchmadePlayer player) { string url = $"{baseUrl}/players/{player.UserId}/rc"; using (var req = UnityWebRequest.Get(url)) { yield return req.SendWebRequest(); if (req.responseCode != 200) { Logger.Log($"Player RC fetch HTTP {(int)req.responseCode}: {req.error} {url}"); yield break; } string text = req.downloadHandler != null ? req.downloadHandler.text : ""; if (string.IsNullOrEmpty(text)) yield break; var resp = JsonUtility.FromJson(text); if (resp != null && resp.ok) player.rc = resp.rc; else if (resp != null && !string.IsNullOrEmpty(resp.error)) Logger.Log($"Player RC fetch: {resp.error} ({url})"); } } [Serializable] class PlayerRcApiResponse { public bool ok; public int player_id; public float rc; public string error; } }