using UnityEngine; using TMPro; using UnityEngine.UI; public class ScoreManager : MonoBehaviour { public static ScoreManager Instance { get; private set; } public int totalScore = 0; // per-track pm score sums (red, green, yellow, purple, blue) public int red_pmScore_sum = 0; public int green_pmScore_sum = 0; public int yellow_pmScore_sum = 0; public int purple_pmScore_sum = 0; public int blue_pmScore_sum = 0; // aggregate of the five track pm sums public int allSum_pmScore = 0; private int[] pmScoreSums = new int[5]; // per-track idol score sums (red, green, yellow, purple, blue) public int red_idolScore_sum = 0; public int green_idolScore_sum = 0; public int yellow_idolScore_sum = 0; public int purple_idolScore_sum = 0; public int blue_idolScore_sum = 0; // aggregate of the five track idol sums public int allSum_idolScore = 0; private int[] idolScoreSums = new int[5]; [Header("Judgement Statistics")] public int countPerfect = 0; public int countGreat = 0; public int countGood = 0; public int countMiss = 0; public void ResetStatistics() { countPerfect = countGreat = countGood = countMiss = 0; } private void Awake() { if (Instance == null) Instance = this; else Destroy(gameObject); for (int i = 0; i < pmScoreSums.Length; i++) pmScoreSums[i] = 0; for (int i = 0; i < idolScoreSums.Length; i++) idolScoreSums[i] = 0; ResetStatistics(); } /// /// Add a per-note pm score delta to the specified track (0..4) and update named fields + aggregate. /// Also calculates idol score as pmDelta * scoreEfficiency. /// public void AddPmScoreForTrack(int trackIndex, int pmDelta, float scoreEfficiency) { if (trackIndex < 0 || trackIndex >= pmScoreSums.Length) return; if (pmDelta == 0) return; pmScoreSums[trackIndex] += pmDelta; // clamp at int.MaxValue-1 to avoid overflow if (pmScoreSums[trackIndex] < 0) pmScoreSums[trackIndex] = 0; if (pmScoreSums[trackIndex] > int.MaxValue - 1) pmScoreSums[trackIndex] = int.MaxValue - 1; // calculate idol score: pmDelta * scoreEfficiency int idolDelta = Mathf.FloorToInt(pmDelta * scoreEfficiency); idolScoreSums[trackIndex] += idolDelta; if (idolScoreSums[trackIndex] < 0) idolScoreSums[trackIndex] = 0; if (idolScoreSums[trackIndex] > int.MaxValue - 1) idolScoreSums[trackIndex] = int.MaxValue - 1; // update named fields for easy access red_pmScore_sum = pmScoreSums[0]; green_pmScore_sum = pmScoreSums[1]; yellow_pmScore_sum = pmScoreSums[2]; purple_pmScore_sum = pmScoreSums[3]; blue_pmScore_sum = pmScoreSums[4]; red_idolScore_sum = idolScoreSums[0]; green_idolScore_sum = idolScoreSums[1]; yellow_idolScore_sum = idolScoreSums[2]; purple_idolScore_sum = idolScoreSums[3]; blue_idolScore_sum = idolScoreSums[4]; // recompute aggregates long aggPm = 0; long aggIdol = 0; for (int i = 0; i < pmScoreSums.Length; i++) aggPm += pmScoreSums[i]; for (int i = 0; i < idolScoreSums.Length; i++) aggIdol += idolScoreSums[i]; allSum_pmScore = (int)Mathf.Min((float)aggPm, (float)int.MaxValue - 1f); allSum_idolScore = (int)Mathf.Min((float)aggIdol, (float)int.MaxValue - 1f); Debug.Log($"[ScoreManager] Added {pmDelta} to track {trackIndex} pm sum, idol delta {idolDelta}. New pm sums: R{red_pmScore_sum} G{green_pmScore_sum} Y{yellow_pmScore_sum} P{purple_pmScore_sum} B{blue_pmScore_sum} -> allSumPm={allSum_pmScore}. Idol sums: R{red_idolScore_sum} G{green_idolScore_sum} Y{yellow_idolScore_sum} P{purple_idolScore_sum} B{blue_idolScore_sum} -> allSumIdol={allSum_idolScore}"); // Update UI in teamUIController if available (per-track pm sums + aggregate) var ui = teamUIController.Instance; if (ui != null) { // Legacy Text fields on teamUIController try { if (ui.red_pmScore_sum != null) ui.red_pmScore_sum.text = red_pmScore_sum.ToString(); if (ui.green_pmScore_sum != null) ui.green_pmScore_sum.text = green_pmScore_sum.ToString(); if (ui.yellow_pmScore_sum != null) ui.yellow_pmScore_sum.text = yellow_pmScore_sum.ToString(); if (ui.purple_pmScore_sum != null) ui.purple_pmScore_sum.text = purple_pmScore_sum.ToString(); if (ui.blue_pmScore_sum != null) ui.blue_pmScore_sum.text = blue_pmScore_sum.ToString(); if (ui.allSum_pmScore != null) ui.allSum_pmScore.text = allSum_pmScore.ToString(); if (ui.red_idolScore_sum != null) ui.red_idolScore_sum.text = red_idolScore_sum.ToString(); if (ui.green_idolScore_sum != null) ui.green_idolScore_sum.text = green_idolScore_sum.ToString(); if (ui.yellow_idolScore_sum != null) ui.yellow_idolScore_sum.text = yellow_idolScore_sum.ToString(); if (ui.purple_idolScore_sum != null) ui.purple_idolScore_sum.text = purple_idolScore_sum.ToString(); if (ui.blue_idolScore_sum != null) ui.blue_idolScore_sum.text = blue_idolScore_sum.ToString(); if (ui.allSum_idolScore != null) ui.allSum_idolScore.text = allSum_idolScore.ToString(); } catch (System.Exception ex) { Debug.LogWarning($"[ScoreManager] Failed to write sums to teamUIController fields: {ex}"); } } // Optionally update any UI for pm sums here if teamUIController exposes fields (not implemented by default) // Ensure total is recalculated when pm/idol aggregates change so totalScore reflects pm + idol RecalculateTotal(); } public void RecalculateTotal() { int sum = 0; int[] currents = new int[5]; int[] maxes = new int[5]; for (int i = 1; i <= 5; i++) { var go = GameObject.Find($"ally_0{i}"); if (go == null) { currents[i - 1] = 0; maxes[i - 1] = 0; continue; } var ally = go.GetComponent(); if (ally != null) { currents[i - 1] = ally.currentScore; maxes[i - 1] = ally.maxTrackScore; } else { currents[i - 1] = 0; maxes[i - 1] = 0; } sum += currents[i - 1]; } // totalScore should include both pm (per-note) and idol aggregates maintained by ScoreManager long combined = (long)allSum_pmScore + (long)allSum_idolScore; // clamp to int range totalScore = (int)Mathf.Min((float)combined, (float)int.MaxValue - 1f); // update UI if available if (teamUIController.Instance != null) { var ui = teamUIController.Instance; // helper lambda to set text on TMP or legacy Text under a parent fallback void SetScoreText(TextMeshProUGUI assignedTmp, GameObject parent, int cur, int max, string slotName) { string value = cur + "/" + max; if (assignedTmp != null) { assignedTmp.text = value; Debug.Log($"[ScoreManager] Wrote to assigned TMP for {slotName}: '{value}' -> {assignedTmp.gameObject.name}"); return; } // try find TMP in parent if (parent != null) { var tmp = parent.GetComponentInChildren(true); if (tmp != null) { tmp.text = value; Debug.Log($"[ScoreManager] Wrote to TMP in parent {parent.name} for {slotName}: '{value}' -> {tmp.gameObject.name}"); return; } var legacy = parent.GetComponentInChildren(true); if (legacy != null) { legacy.text = value; Debug.Log($"[ScoreManager] Wrote to legacy Text in parent {parent.name} for {slotName}: '{value}' -> {legacy.gameObject.name}"); return; } } Debug.LogWarning($"[ScoreManager] Could not find UI to write score for {slotName}. assignedTmp is null and parent '{parent?.name}' has no TMP/Text children."); } // Update each slot: use the explicit TMP fields if set; otherwise try parent object fields SetScoreText(ui.teammate01_current_scoreText, ui.objectFather_ally01, currents[0], maxes[0], "teammate01"); SetScoreText(ui.teammate02_current_scoreText, ui.objectFather_ally02, currents[1], maxes[1], "teammate02"); SetScoreText(ui.teammate03_current_scoreText, ui.objectFather_ally03, currents[2], maxes[2], "teammate03"); SetScoreText(ui.teammate04_current_scoreText, ui.objectFather_ally04, currents[3], maxes[3], "teammate04"); SetScoreText(ui.teammate05_current_scoreText, ui.objectFather_ally05, currents[4], maxes[4], "teammate05"); // update total score (try TMP first, then legacy Text) if (ui.currentTotalScore != null) { var go = ui.currentTotalScore.gameObject; if (go != null) { var tmpComp = go.GetComponent(); if (tmpComp != null) { tmpComp.text = totalScore.ToString(); Debug.Log($"[ScoreManager] Wrote total to TMP: {totalScore} -> {tmpComp.gameObject.name}"); } else { var legacyComp = go.GetComponent(); if (legacyComp != null) { legacyComp.text = totalScore.ToString(); Debug.Log($"[ScoreManager] Wrote total to legacy Text: {totalScore} -> {legacyComp.gameObject.name}"); } else { ui.currentTotalScore.text = totalScore.ToString(); // fallback Debug.Log($"[ScoreManager] Wrote total to currentTotalScore field fallback: {totalScore}"); } } } else { ui.currentTotalScore.text = totalScore.ToString(); Debug.Log($"[ScoreManager] Wrote total to currentTotalScore fallback (no go): {totalScore}"); } } else { Debug.LogWarning("[ScoreManager] teamUIController.currentTotalScore is null; cannot display total score."); } } else { Debug.LogWarning("[ScoreManager] teamUIController.Instance is null; cannot update UI."); } } }