diff --git a/MiraAPI/Modifiers/BaseModifier.cs b/MiraAPI/Modifiers/BaseModifier.cs index cf108b3..3daeb56 100644 --- a/MiraAPI/Modifiers/BaseModifier.cs +++ b/MiraAPI/Modifiers/BaseModifier.cs @@ -107,17 +107,20 @@ public abstract class BaseModifier : IOptionable /// /// The guide object. /// The title text object. + /// The title's icon. /// The scroller parent. /// The of the wiki. - public virtual GameObject GetAdvancedWiki(MatchInfoGuide guide, TextMeshPro titleText, Scroller parent) + public virtual GameObject GetAdvancedWiki(MatchInfoGuide guide, TextMeshPro titleText, SpriteRenderer titleIcon, Scroller parent) { var abilities = WikiAbilities; return Helpers.CreateAdvancedWikiPage( guide, titleText, + titleIcon, parent, ModifierNameLocale, - $"{this.GetTmpIcon()} {ModifierName} ({ModifierCategoryTitle})".TrimStart(), + $"{ModifierName} ({ModifierCategoryTitle})".TrimStart(), + ModifierIcon ?? MiraAssets.IconNeutral.LoadAsset(), ModifierWikiDescription, abilities); } diff --git a/MiraAPI/Patches/RoleGuidePatches.cs b/MiraAPI/Patches/RoleGuidePatches.cs index 77f9cf4..92080e8 100644 --- a/MiraAPI/Patches/RoleGuidePatches.cs +++ b/MiraAPI/Patches/RoleGuidePatches.cs @@ -55,6 +55,7 @@ public static class RoleGuidePatches private static TextBoxTMP _searchBoxTmp; private static GameObject _currentAdvancedTabObject; private static TextMeshPro _titleText; + private static SpriteRenderer _titleIcon; private static bool _suppressSearchRefresh; private static IEnumerator? _searchDebounce; private static string _appliedSearch = string.Empty; @@ -145,6 +146,7 @@ public static class RoleGuidePatches _appliedSearch = string.Empty; _suppressSearchRefresh = false; _titleText = null!; + _titleIcon = null!; _searchBoxTmp = null!; _rolesScroller = null!; _modifiersScroller = null!; @@ -254,9 +256,18 @@ public static class RoleGuidePatches _titleText = __instance.transitionOpen.transform.FindChild("Text_Title")?.GetComponent()!; if (_titleText) { + _titleText.transform.localPosition += new Vector3(0.5f, 0); _titleText.transform.GetComponent().Destroy(); } } + if (!_titleIcon) + { + var titleIconObj = new GameObject("TitleIcon"); + _titleIcon = titleIconObj.AddComponent(); + _titleIcon.transform.SetParent(_titleText.transform.parent); + _titleIcon.transform.localPosition = new Vector3(-2.75f, 1.4f, 0); + titleIconObj.layer = _titleText.gameObject.layer; + } if (_titleText) { @@ -1247,26 +1258,33 @@ public static class RoleGuidePatches [HarmonyPatch(typeof(MatchInfoGuide), nameof(MatchInfoGuide.SetActiveTab))] private static void SetActiveTab(int tabIndex) { - if (_titleText) + if (_titleText && _titleIcon) { switch (tabIndex) { case 0: _titleText.text = MiraLocaleManager.Get("MiraApi.Wiki.PlayersTab"); + _titleIcon.sprite = MiraAssets.IconPlayerList.LoadAsset(); break; case 1: _titleText.text = MiraLocaleManager.Get("MiraApi.Wiki.SettingsTab"); + _titleIcon.sprite = MiraAssets.IconSettings.LoadAsset(); break; case RolesTabIndex: _titleText.text = MiraLocaleManager.Get("Roles"); + _titleIcon.sprite = GetRandomRoleIcon(); break; case ModifiersTabIndex: _titleText.text = MiraLocaleManager.Get("Modifiers"); + _titleIcon.sprite = GetRandomModifierIcon(); break; default: _titleText.text = TranslationController.Instance.GetString(StringNames.MatchInfoGuideTitle); + _titleIcon.sprite = MiraAssets.IconPlayerList.LoadAsset(); break; } + + _titleIcon.SetSizeLimit(0.55f); } _advancedInfoTabScroller?.gameObject.SetActive(false); @@ -1274,6 +1292,45 @@ public static class RoleGuidePatches UpdateSpinner(); } + public static Sprite GetRandomModifierIcon() + { + var activeMods = PlayerControl.LocalPlayer.GetModifiers() + .Where(x => !x.HideOnUi && x.ModifierIcon != null).ToList(); + if (activeMods.Count > 0) + { + return activeMods.Random()!.ModifierIcon!.LoadAsset(); + } + + return GetRandomFactionIcon(); + } + + public static Sprite GetRandomRoleIcon() + { + var aliveRole = PlayerControl.LocalPlayer.Data?.Role; + if (aliveRole != null && aliveRole.RoleIconSolid != null) + { + return aliveRole.RoleIconSolid; + } + + return GetRandomFactionIcon(); + } + + public static Sprite GetRandomFactionIcon() + { + var random = UnityEngine.Random.Range(1, 4); + if (random == 1) + { + return MiraAssets.IconCrewmate.LoadAsset(); + } + + if (random == 2) + { + return MiraAssets.IconImpostor.LoadAsset(); + } + + return MiraAssets.IconNeutral.LoadAsset(); + } + private static bool TryPrepareAdvancedWiki(MatchInfoGuide instance) { instance.settingsTabs[RolesTabIndex].SetActive(false); @@ -1325,7 +1382,7 @@ public static class RoleGuidePatches return; } - _currentAdvancedTabObject = modifier.GetAdvancedWiki(instance, _titleText, _advancedInfoTabScroller); + _currentAdvancedTabObject = modifier.GetAdvancedWiki(instance, _titleText, _titleIcon, _advancedInfoTabScroller); } public static void DisplayAdvancedWiki(MatchInfoGuide instance, RoleBehaviour role) @@ -1345,11 +1402,11 @@ public static class RoleGuidePatches if (role is ICustomRole custom) { - _currentAdvancedTabObject = custom.GetAdvancedWiki(instance, _titleText, _advancedInfoTabScroller); + _currentAdvancedTabObject = custom.GetAdvancedWiki(instance, _titleText, _titleIcon, _advancedInfoTabScroller); } else { - var titleTxt = $"{role.GetTmpIcon()} {role.GetRoleName()}" + + var titleTxt = $"{role.GetRoleName()}" + $" ({TranslationController.Instance.GetString(role.TeamType is RoleTeamTypes.Crewmate ? StringNames.Crewmate : StringNames.Impostor)})"; var description = TranslationController.Instance.GetString(role.BlurbNameLong); if (description.Contains("STRMISS")) @@ -1364,9 +1421,11 @@ public static class RoleGuidePatches _currentAdvancedTabObject = Helpers.CreateAdvancedWikiPage( instance, _titleText, + _titleIcon, _advancedInfoTabScroller, role.Role.ToString(), titleTxt, + role.RoleIconColor, description, []); } diff --git a/MiraAPI/Resources/Wiki/IconCrewmate.png b/MiraAPI/Resources/Wiki/IconCrewmate.png new file mode 100644 index 0000000..61f706f Binary files /dev/null and b/MiraAPI/Resources/Wiki/IconCrewmate.png differ diff --git a/MiraAPI/Resources/Wiki/IconImpostor.png b/MiraAPI/Resources/Wiki/IconImpostor.png new file mode 100644 index 0000000..6100cd1 Binary files /dev/null and b/MiraAPI/Resources/Wiki/IconImpostor.png differ diff --git a/MiraAPI/Resources/Wiki/IconNeutral.png b/MiraAPI/Resources/Wiki/IconNeutral.png new file mode 100644 index 0000000..984041c Binary files /dev/null and b/MiraAPI/Resources/Wiki/IconNeutral.png differ diff --git a/MiraAPI/Resources/Wiki/IconPlayerList.png b/MiraAPI/Resources/Wiki/IconPlayerList.png new file mode 100644 index 0000000..234baa0 Binary files /dev/null and b/MiraAPI/Resources/Wiki/IconPlayerList.png differ diff --git a/MiraAPI/Resources/Wiki/IconSettings.png b/MiraAPI/Resources/Wiki/IconSettings.png new file mode 100644 index 0000000..50452dc Binary files /dev/null and b/MiraAPI/Resources/Wiki/IconSettings.png differ diff --git a/MiraAPI/Resources/Wiki/IconTerminology.png b/MiraAPI/Resources/Wiki/IconTerminology.png new file mode 100644 index 0000000..8b95d62 Binary files /dev/null and b/MiraAPI/Resources/Wiki/IconTerminology.png differ diff --git a/MiraAPI/Roles/ICustomRole.cs b/MiraAPI/Roles/ICustomRole.cs index 307b6ca..4d5e247 100644 --- a/MiraAPI/Roles/ICustomRole.cs +++ b/MiraAPI/Roles/ICustomRole.cs @@ -318,17 +318,20 @@ public interface ICustomRole : IOptionable /// /// The guide object. /// The title text object. + /// The title's icon. /// The scroller parent. /// The of the wiki. - GameObject GetAdvancedWiki(MatchInfoGuide guide, TextMeshPro titleText, Scroller parent) + GameObject GetAdvancedWiki(MatchInfoGuide guide, TextMeshPro titleText, SpriteRenderer titleIcon, Scroller parent) { var abilities = WikiAbilities; return Helpers.CreateAdvancedWikiPage( guide, titleText, + titleIcon, parent, RoleNameLocale, - $"{this.GetTmpIcon()} {RoleName} ({RoleFactionTitle})", + $"{RoleName} ({RoleFactionTitle})", + Configuration.Icon ?? MiraAssets.IconNeutral.LoadAsset(), RoleWikiDescription, abilities); } diff --git a/MiraAPI/Utilities/Assets/MiraAssets.cs b/MiraAPI/Utilities/Assets/MiraAssets.cs index a57332b..0feb75c 100644 --- a/MiraAPI/Utilities/Assets/MiraAssets.cs +++ b/MiraAPI/Utilities/Assets/MiraAssets.cs @@ -305,5 +305,35 @@ public static class MiraAssets /// public static LoadableResourceAsset VisibleOnIdleSprite { get; } = new("MiraAPI.Resources.Wiki.VisibleOnIdle.png"); + /// + /// Gets the sprite used for crewmates. + /// + public static LoadableResourceAsset IconCrewmate { get; } = new("MiraAPI.Resources.Wiki.IconCrewmate.png"); + + /// + /// Gets the sprite used for impostors. + /// + public static LoadableResourceAsset IconImpostor { get; } = new("MiraAPI.Resources.Wiki.IconImpostor.png"); + + /// + /// Gets the sprite used for neutrals. + /// + public static LoadableResourceAsset IconNeutral { get; } = new("MiraAPI.Resources.Wiki.IconNeutral.png"); + + /// + /// Gets the sprite used for the player list. + /// + public static LoadableResourceAsset IconPlayerList { get; } = new("MiraAPI.Resources.Wiki.IconPlayerList.png"); + + /// + /// Gets the sprite used for settings. + /// + public static LoadableResourceAsset IconSettings { get; } = new("MiraAPI.Resources.Wiki.IconSettings.png"); + + /// + /// Gets the sprite used for terminology. + /// + public static LoadableResourceAsset IconTerminology { get; } = new("MiraAPI.Resources.Wiki.IconTerminology.png"); + internal static LoadableResourceAsset BlankSprite { get; } = new("MiraAPI.Resources.BlankSprite.png"); } diff --git a/MiraAPI/Utilities/Helpers.cs b/MiraAPI/Utilities/Helpers.cs index 4587f36..773a4ae 100644 --- a/MiraAPI/Utilities/Helpers.cs +++ b/MiraAPI/Utilities/Helpers.cs @@ -741,15 +741,19 @@ public static class Helpers /// The guide panel to attach the tab to. /// The name of the tab. /// The title of the tab. + /// The icon of the page. /// The description of the tab. /// The instance of the title. + /// The instance for the title. /// The instance of the description. /// The of the tab. - public static GameObject CreateAdvancedWikiTab(MatchInfoGuide guide, string objName, string title, string description, TextMeshPro titleTmp, out TextMeshPro descriptionTmp) + public static GameObject CreateAdvancedWikiTab(MatchInfoGuide guide, string objName, string title, Sprite icon, string description, TextMeshPro titleTmp, SpriteRenderer titleIcon, out TextMeshPro descriptionTmp) { var obj = new GameObject(objName); titleTmp.richText = true; titleTmp.text = title; + titleIcon.sprite = icon; + titleIcon.SetSizeLimit(0.55f); descriptionTmp = Object.Instantiate(guide.MatchInfoRolePanelPrefab.roleCount, obj.transform); descriptionTmp.fontSizeMin = descriptionTmp.fontSizeMax = descriptionTmp.fontSize = 2f; var sourceTmp = HudManager.Instance.TaskPanel.taskText; @@ -769,9 +773,11 @@ public static class Helpers /// /// The guide object. /// The instance of the title. + /// The instance for the title. /// The the page should be parented to. /// The name of the page object. /// The title of the page. + /// The icon of the page. /// The description of the page. /// The abilities to display in a grid below the description. /// Whether to use variable text sizing for ability descriptions (allows different heights). @@ -779,9 +785,11 @@ public static class Helpers public static GameObject CreateAdvancedWikiPage( MatchInfoGuide guide, TextMeshPro titleTmp, + SpriteRenderer titleIcon, Scroller parent, string objName, string title, + Sprite icon, string description, IReadOnlyCollection abilities, bool variableTextSizing = false) @@ -791,8 +799,10 @@ public static class Helpers guide, objName, title, + icon, description, titleTmp, + titleIcon, out var desc); var num = 0; var maxTextSize = 0f;