using System; using System.Collections.Generic; using System.Collections.ObjectModel; using JetBrains.Annotations; using RoR2.Stats; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; namespace RoR2.UI; [RequireComponent(typeof(MPEventSystemProvider))] public class GameEndReportPanelController : MonoBehaviour { public struct DisplayData : IEquatable { [CanBeNull] public RunReport runReport; public int playerIndex; public bool Equals(DisplayData other) { if (object.Equals(runReport, other.runReport)) { return playerIndex == other.playerIndex; } return false; } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is DisplayData other) { return Equals(other); } return false; } public override int GetHashCode() { return ((-1418150836 * -1521134295 + base.GetHashCode()) * -1521134295 + EqualityComparer.Default.GetHashCode(runReport)) * -1521134295 + playerIndex.GetHashCode(); } } [Header("Result")] [Tooltip("The TextMeshProUGUI component to use to display the result of the game: Win or Loss")] public TextMeshProUGUI resultLabel; public Image resultIconBackgroundImage; public Image resultIconForegroundImage; public HGTextMeshProUGUI finalMessageLabel; [Tooltip("The Image component to use to display the selected difficulty of the run.")] [Header("Run Settings")] public Image selectedDifficultyImage; [Tooltip("The LanguageTextMeshController component to use to display the selected difficulty of the run.")] public LanguageTextMeshController selectedDifficultyLabel; [Tooltip("The ArtifactDisplayPanelController component to send the enabled artifacts of the run to.")] public ArtifactDisplayPanelController artifactDisplayPanelController; [Tooltip("A list of StatDef names to display in the stats section.")] [Header("Stats")] public string[] statsToDisplay; [Tooltip("Prefab to be used for stat display.")] public GameObject statStripPrefab; [Tooltip("The RectTransform in which to build the stat strips.")] public RectTransform statContentArea; [Tooltip("The TextMeshProUGUI component used to display the total points.")] public TextMeshProUGUI totalPointsLabel; [Tooltip("Prefab to be used for unlock display.")] [Header("Unlocks")] public GameObject unlockStripPrefab; [Tooltip("The RectTransform in which to build the unlock strips.")] public RectTransform unlockContentArea; [Header("Items")] [Tooltip("The inventory display controller.")] public ItemInventoryDisplay itemInventoryDisplay; [Tooltip("The RawImage component to use to display the player character's portrait.")] [Header("Player Info")] public RawImage playerBodyPortraitImage; [Tooltip("The TextMeshProUGUI component to use to display the player character's body name.")] public TextMeshProUGUI playerBodyLabel; [Tooltip("The TextMeshProUGUI component to use to display the player's username.")] public TextMeshProUGUI playerUsernameLabel; [Tooltip("The RawImage component to use to display the killer character's portrait.")] [Header("Killer Info")] public RawImage killerBodyPortraitImage; [Tooltip("The TextMeshProUGUI component to use to display the killer character's body name.")] public TextMeshProUGUI killerBodyLabel; [Tooltip("The GameObject used as the panel for the killer information. This is used to disable the killer panel when the player has won the game.")] public GameObject killerPanelObject; [Header("Navigation and Misc")] public MPButton continueButton; public RectTransform chatboxTransform; public CarouselNavigationController playerNavigationController; public RectTransform selectedPlayerEffectRoot; public RectTransform acceptButtonArea; private readonly List statStrips = new List(); private readonly List unlockStrips = new List(); public DisplayData displayData { get; private set; } private void Awake() { playerNavigationController.onPageChangeSubmitted += OnPlayerNavigationControllerPageChangeSubmitted; SetContinueButtonAction(null); } private void AllocateStatStrips(int count) { while (statStrips.Count > count) { int index = statStrips.Count - 1; UnityEngine.Object.Destroy(statStrips[index].gameObject); statStrips.RemoveAt(index); } while (statStrips.Count < count) { GameObject gameObject = UnityEngine.Object.Instantiate(statStripPrefab, statContentArea); gameObject.SetActive(value: true); statStrips.Add(gameObject); } } private void AllocateUnlockStrips(int count) { while (unlockStrips.Count > count) { int index = unlockStrips.Count - 1; UnityEngine.Object.Destroy(unlockStrips[index].gameObject); unlockStrips.RemoveAt(index); } while (unlockStrips.Count < count) { GameObject gameObject = UnityEngine.Object.Instantiate(unlockStripPrefab, unlockContentArea); gameObject.SetActive(value: true); unlockStrips.Add(gameObject); } } public void SetDisplayData(DisplayData newDisplayData) { if (displayData.Equals(newDisplayData)) { return; } displayData = newDisplayData; bool flag = (bool)Run.instance && displayData.runReport != null && Run.instance.GetUniqueId() == displayData.runReport.runGuid; if ((bool)resultLabel && (bool)resultIconBackgroundImage && (bool)resultIconForegroundImage) { GameEndingDef gameEndingDef = null; if (displayData.runReport != null) { gameEndingDef = displayData.runReport.gameEnding; } resultLabel.gameObject.SetActive(gameEndingDef); resultIconBackgroundImage.gameObject.SetActive(gameEndingDef); resultIconForegroundImage.gameObject.SetActive(gameEndingDef); if ((bool)gameEndingDef) { resultLabel.text = Language.GetString(gameEndingDef.endingTextToken); resultIconBackgroundImage.color = gameEndingDef.backgroundColor; resultIconForegroundImage.color = gameEndingDef.foregroundColor; resultIconForegroundImage.sprite = gameEndingDef.icon; resultIconBackgroundImage.material = gameEndingDef.material; } } DifficultyIndex difficultyIndex = DifficultyIndex.Invalid; if (displayData.runReport != null) { difficultyIndex = displayData.runReport.ruleBook.FindDifficulty(); } DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(difficultyIndex); if ((bool)selectedDifficultyImage) { selectedDifficultyImage.sprite = difficultyDef?.GetIconSprite(); } if ((bool)selectedDifficultyLabel) { selectedDifficultyLabel.token = difficultyDef?.nameToken; } if ((bool)artifactDisplayPanelController) { RuleBook ruleBook = displayData.runReport.ruleBook; List list = new List(ArtifactCatalog.artifactCount); for (int i = 0; i < RuleCatalog.choiceCount; i++) { RuleChoiceDef choiceDef = RuleCatalog.GetChoiceDef(i); if (choiceDef.artifactIndex != ArtifactIndex.None && ruleBook.GetRuleChoice(choiceDef.ruleDef) == choiceDef) { list.Add(ArtifactCatalog.GetArtifactDef(choiceDef.artifactIndex)); } } List.Enumerator enabledArtifacts = list.GetEnumerator(); artifactDisplayPanelController.SetDisplayData(ref enabledArtifacts); } RunReport.PlayerInfo playerInfo = displayData.runReport?.GetPlayerInfoSafe(displayData.playerIndex); SetPlayerInfo(playerInfo, displayData.playerIndex); int pageCount = displayData.runReport?.playerInfoCount ?? 0; playerNavigationController.gameObject.SetActive((displayData.runReport?.playerInfoCount ?? 0) > 1); if ((bool)chatboxTransform) { chatboxTransform.gameObject.SetActive(!RoR2Application.isInSinglePlayer && flag); } playerNavigationController.SetDisplayData(new CarouselNavigationController.DisplayData(pageCount, displayData.playerIndex)); ReadOnlyCollection elements = playerNavigationController.buttonAllocator.elements; for (int j = 0; j < elements.Count; j++) { MPButton mPButton = elements[j]; RunReport.PlayerInfo playerInfo2 = displayData.runReport.GetPlayerInfo(j); CharacterBody bodyPrefabBodyComponent = BodyCatalog.GetBodyPrefabBodyComponent(playerInfo2.bodyIndex); Texture texture = (bodyPrefabBodyComponent ? bodyPrefabBodyComponent.portraitIcon : null); mPButton.GetComponentInChildren().texture = texture; mPButton.GetComponent().SetContent(TooltipProvider.GetPlayerNameTooltipContent(playerInfo2.name)); } selectedPlayerEffectRoot.transform.SetParent(playerNavigationController.buttonAllocator.elements[displayData.playerIndex].transform); selectedPlayerEffectRoot.gameObject.SetActive(value: false); selectedPlayerEffectRoot.gameObject.SetActive(value: true); selectedPlayerEffectRoot.offsetMin = Vector2.zero; selectedPlayerEffectRoot.offsetMax = Vector2.zero; selectedPlayerEffectRoot.localScale = Vector3.one; } public void SetContinueButtonAction(UnityAction action) { continueButton.onClick.RemoveAllListeners(); if (action != null) { continueButton.onClick.AddListener(action); } acceptButtonArea.gameObject.SetActive(action != null); } private void OnPlayerNavigationControllerPageChangeSubmitted(int newPage) { DisplayData displayData = this.displayData; displayData.playerIndex = newPage; SetDisplayData(displayData); } private void SetPlayerInfo([CanBeNull] RunReport.PlayerInfo playerInfo, int playerIndex) { ulong num = 0uL; if (playerInfo != null && playerInfo.statSheet != null) { StatSheet statSheet = playerInfo.statSheet; AllocateStatStrips(statsToDisplay.Length); for (int i = 0; i < statsToDisplay.Length; i++) { string text = statsToDisplay[i]; StatDef statDef = StatDef.Find(text); if (statDef == null) { Debug.LogWarningFormat("GameEndReportPanelController.SetStatSheet: Could not find stat def \"{0}\".", text); } else { AssignStatToStrip(statSheet, statDef, statStrips[i]); num += statSheet.GetStatPointValue(statDef); } } int unlockableCount = statSheet.GetUnlockableCount(); int num2 = 0; for (int j = 0; j < unlockableCount; j++) { UnlockableDef unlockable = statSheet.GetUnlockable(j); if (unlockable != null && !unlockable.hidden) { num2++; } } AllocateUnlockStrips(num2); int num3 = 0; for (int k = 0; k < unlockableCount; k++) { UnlockableDef unlockable2 = statSheet.GetUnlockable(k); if (unlockable2 != null && !unlockable2.hidden) { AssignUnlockToStrip(unlockable2, unlockStrips[num3]); num3++; } } if ((bool)itemInventoryDisplay && playerInfo.itemAcquisitionOrder != null) { itemInventoryDisplay.SetItems(playerInfo.itemAcquisitionOrder, playerInfo.itemAcquisitionOrder.Length, playerInfo.itemStacks); itemInventoryDisplay.UpdateDisplay(); } string token = playerInfo.finalMessageToken + "_2P"; if (Language.IsTokenInvalid(token)) { token = playerInfo.finalMessageToken; } finalMessageLabel.SetText(Language.GetStringFormatted(token, playerInfo.name)); } else { AllocateStatStrips(0); AllocateUnlockStrips(0); if ((bool)itemInventoryDisplay) { itemInventoryDisplay.ResetItems(); } finalMessageLabel.SetText(string.Empty); } string @string = Language.GetString("STAT_POINTS_FORMAT"); totalPointsLabel.text = string.Format(@string, TextSerialization.ToStringNumeric(num)); GameObject gameObject = null; if (playerInfo != null) { gameObject = BodyCatalog.GetBodyPrefab(playerInfo.bodyIndex); } string text2 = ""; Texture texture = null; if ((bool)gameObject) { texture = gameObject.GetComponent().portraitIcon; text2 = Language.GetString(gameObject.GetComponent().baseNameToken); if (playerIndex == 0) { if (PlatformSystems.userManager.ShouldAlwaysUseCurrentDisplayName()) { playerUsernameLabel.text = PlatformSystems.userManager.GetUserName(); } else { playerUsernameLabel.text = playerInfo.name; } } else if (PlatformSystems.userManager.ShouldHideOtherDisplayNames()) { playerUsernameLabel.text = text2; } else { playerUsernameLabel.text = playerInfo.name; } } string string2 = Language.GetString("STAT_CLASS_NAME_FORMAT"); playerBodyLabel.text = string.Format(string2, text2); playerBodyPortraitImage.texture = texture; GameObject gameObject2 = null; if (playerInfo != null) { gameObject2 = BodyCatalog.GetBodyPrefab(playerInfo.killerBodyIndex); killerPanelObject?.SetActive(playerInfo.isDead); } string string3 = Language.GetString("UNIDENTIFIED_KILLER_NAME"); Texture texture2 = LegacyResourcesAPI.Load("Textures/BodyIcons/texUnidentifiedKillerIcon"); if ((bool)gameObject2) { Texture portraitIcon = gameObject2.GetComponent().portraitIcon; string baseNameToken = gameObject2.GetComponent().baseNameToken; if (portraitIcon != null) { texture2 = portraitIcon; } if (!Language.IsTokenInvalid(baseNameToken)) { string3 = Language.GetString(gameObject2.GetComponent().baseNameToken); } } string string4 = Language.GetString("STAT_KILLER_NAME_FORMAT"); killerBodyLabel.text = string.Format(string4, string3); killerBodyPortraitImage.texture = texture2; } private void AssignStatToStrip([CanBeNull] StatSheet srcStatSheet, [NotNull] StatDef statDef, GameObject destStatStrip) { string arg = "0"; ulong value = 0uL; if (srcStatSheet != null) { arg = srcStatSheet.GetStatDisplayValue(statDef); value = srcStatSheet.GetStatPointValue(statDef); } string @string = Language.GetString(statDef.displayToken); string text = string.Format(Language.GetString("STAT_NAME_VALUE_FORMAT"), @string, arg); destStatStrip.transform.Find("StatNameLabel").GetComponent().text = text; string string2 = Language.GetString("STAT_POINTS_FORMAT"); destStatStrip.transform.Find("PointValueLabel").GetComponent().text = string.Format(string2, TextSerialization.ToStringNumeric(value)); } private void AssignUnlockToStrip(UnlockableDef unlockableDef, GameObject destUnlockableStrip) { AchievementDef achievementDefFromUnlockable = AchievementManager.GetAchievementDefFromUnlockable(unlockableDef.cachedName); Texture texture = null; string @string = Language.GetString("TOOLTIP_UNLOCK_GENERIC_NAME"); string string2 = Language.GetString("TOOLTIP_UNLOCK_GENERIC_DESCRIPTION"); if (unlockableDef.cachedName.Contains("Items.")) { @string = Language.GetString("TOOLTIP_UNLOCK_ITEM_NAME"); string2 = Language.GetString("TOOLTIP_UNLOCK_ITEM_DESCRIPTION"); } else if (unlockableDef.cachedName.Contains("Logs.")) { @string = Language.GetString("TOOLTIP_UNLOCK_LOG_NAME"); string2 = Language.GetString("TOOLTIP_UNLOCK_LOG_DESCRIPTION"); } else if (unlockableDef.cachedName.Contains("Characters.")) { @string = Language.GetString("TOOLTIP_UNLOCK_SURVIVOR_NAME"); string2 = Language.GetString("TOOLTIP_UNLOCK_SURVIVOR_DESCRIPTION"); } else if (unlockableDef.cachedName.Contains("Artifacts.")) { @string = Language.GetString("TOOLTIP_UNLOCK_ARTIFACT_NAME"); string2 = Language.GetString("TOOLTIP_UNLOCK_ARTIFACT_DESCRIPTION"); } string string3; if (achievementDefFromUnlockable != null) { texture = achievementDefFromUnlockable.GetAchievedIcon().texture; string3 = Language.GetString(achievementDefFromUnlockable.nameToken); } else { string3 = Language.GetString(unlockableDef.nameToken); } if (texture != null) { destUnlockableStrip.transform.Find("IconImage").GetComponent().texture = texture; } destUnlockableStrip.transform.Find("NameLabel").GetComponent().text = string3; destUnlockableStrip.GetComponent().overrideTitleText = @string; destUnlockableStrip.GetComponent().overrideBodyText = string2; } }