From 5e6645ff3b11b9db8b2f9642ee39475d09284908 Mon Sep 17 00:00:00 2001
From: Atony <75191600+AtonyGit@users.noreply.github.com>
Date: Sun, 4 Oct 2026 11:49:19 -0500
Subject: [PATCH] Add wiki components to modifiers
---
MiraAPI/Modifiers/BaseModifier.cs | 133 +++++++++++++++++++++++-
MiraAPI/Modifiers/Types/GameModifier.cs | 3 +
2 files changed, 135 insertions(+), 1 deletion(-)
diff --git a/MiraAPI/Modifiers/BaseModifier.cs b/MiraAPI/Modifiers/BaseModifier.cs
index 0017fd9..0ca73e0 100644
--- a/MiraAPI/Modifiers/BaseModifier.cs
+++ b/MiraAPI/Modifiers/BaseModifier.cs
@@ -1,8 +1,16 @@
using System;
+using System.Collections.Generic;
+using Il2CppInterop.Runtime.Attributes;
using MiraAPI.GameOptions;
using MiraAPI.PluginLoading;
+using MiraAPI.Roles;
+using MiraAPI.Translation;
+using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
+using TMPro;
using UnityEngine;
+using UnityEngine.UI;
+using Object = UnityEngine.Object;
namespace MiraAPI.Modifiers;
@@ -44,16 +52,134 @@ public abstract class BaseModifier : IOptionable
x => x.InternalModifiers.Exists(y => y.TypeId == TypeId))
?? throw new InvalidOperationException("Modifier is not registered.");
+ ///
+ /// Gets the id part used to build the modifier's translation keys. It is recommended to simply call it what the modifier is, as other mods may utilize it.
+ ///
+ public virtual string IdPart => GetType().Name;
+
+ ///
+ /// Gets the id part used to build the modifier's translation keys. It is recommended to call it ModGuid.Modifier.Type.
+ ///
+ public virtual string IdPrefix => GetType().Namespace!;
+
///
/// Gets the modifier name.
///
- public abstract string ModifierName { get; }
+ public virtual string ModifierName => MiraLocaleManager.Get(ModifierNameLocale);
+
+ ///
+ /// Gets the modifier's name id for localization.
+ ///
+ public virtual string ModifierNameLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart);
+
+ ///
+ /// Gets the medium description of the modifier. Used in the modifier guide and options menu.
+ ///
+ public virtual string ModifierMedDescription => MiraLocaleManager.Get(ModifierMedDescriptionLocale, GetDescription());
+
+ ///
+ /// Gets the modifier's medium description id for localization.
+ ///
+ public virtual string ModifierMedDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart, "MedDescription");
+
+ ///
+ /// Gets the wiki description of the modifier. Used in the wiki and normally appends the options text as well.
+ ///
+ public virtual string ModifierWikiDescription => MiraLocaleManager.Get(ModifierWikiDescriptionLocale, GetDescription()) +
+ Helpers.GetOptionsText(GetType());
+
+ ///
+ /// Gets the modifier's wiki description id for localization.
+ ///
+ public virtual string ModifierWikiDescriptionLocale => MiraLocaleManager.BuildTranslationId(IdPrefix, IdPart, "WikiDescription");
+
+ ///
+ /// Gets the category of the modifier. Used in the wiki.
+ ///
+ public virtual string ModifierCategoryTitle => MiraLocaleManager.Get("Modifier");
+
+ ///
+ /// Gets whether the modifier is forcibly shown or disabled in the wiki screen.
+ ///
+ /// if the modifier is always displayed, otherwise if it is never displayable, or if it is dictated by amount and chance.
+ public virtual bool? ForceShowModifierOnWiki => false;
+
+ ///
+ /// Gets the information to display in the wiki.
+ ///
+ /// The guide object.
+ /// The title text object.
+ /// The scroller parent.
+ /// The of the wiki.
+ public virtual GameObject GetAdvancedWiki(MatchInfoGuide guide, TextMeshPro titleText, Scroller parent)
+ {
+ parent.ScrollToTop();
+ var obj = Helpers.CreateAdvancedWikiTab(
+ guide,
+ ModifierNameLocale,
+ ModifierName + $" ({ModifierCategoryTitle})",
+ ModifierWikiDescription,
+ titleText,
+ out var desc);
+ var num = 0;
+ if (WikiAbilities.Count != 0)
+ {
+ var grid = Object.Instantiate(parent.Inner, obj.transform);
+ var layoutGroup = grid.GetComponent();
+ layoutGroup.startAxis = GridLayoutGroup.Axis.Vertical;
+ layoutGroup.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
+ layoutGroup.spacing = new Vector2(0.75f, 0.4f);
+ grid.DestroyChildren();
+ foreach (var ability in WikiAbilities)
+ {
+ num++;
+ var panel = Object.Instantiate(
+ guide.MatchInfoRolePanelPrefab,
+ grid);
+ panel.roleCount.text = ability.AbilityType;
+ panel.roleCount.transform.localPosition += new Vector3(-0.04f, 0);
+ panel.roleName.text = ability.Name;
+ panel.roleName.transform.localPosition += new Vector3(-0.04f, 0);
+ panel.roleDescription.text = ability.Description;
+ panel.roleDescription.rectTransform.sizeDelta = new Vector2(2.601f, 0.8f);
+ panel.roleDescription.transform.localPosition += new Vector3(0, -0.1f);
+ panel.roleIcon.sprite = ability.Icon.LoadAsset();
+ panel.roleIcon.SetSizeLimit(0.13f);
+
+ panel.roleIcon.material.SetInt(PlayerMaterial.MaskLayer, 50);
+ panel.roleName.fontMaterial.SetFloat(panel.STENCIL_NAME, 50f);
+ panel.roleDescription.fontMaterial.SetFloat(panel.STENCIL_NAME, 50f);
+ panel.roleCount.fontMaterial.SetFloat(panel.STENCIL_NAME, 50f);
+ panel.roleIcon.transform.localScale = new Vector3(3.5f, 3.5f, 1f);
+ }
+
+ grid.localPosition = new Vector3(-3.9f, 1.1f - desc.textBounds.size.y, 0f);
+ grid.localScale = new Vector3(1.3f, 1.3f, 1);
+ }
+
+ obj.transform.SetParent(parent.Inner.transform);
+ obj.transform.localPosition = new Vector3(0f, 0f, 0f);
+ parent.SetYBoundsMax(Mathf.Clamp(desc.textBounds.size.y - 2 + Mathf.Ceil(num / 2f) * 1.45f, 0f, 999f));
+ return obj;
+ }
+
+ ///
+ /// Gets the list of abilities or other similar information to display below the text of a modifier's wiki page.
+ ///
+ [HideFromIl2Cpp]
+ public virtual List WikiAbilities => [];
///
/// Gets the modifier icon. Useless if is .
///
public virtual LoadableAsset? ModifierIcon => null;
+ ///
+ /// Gets the for the Modifier Icon.
+ ///
+ [HideFromIl2Cpp]
+ public virtual TMP_SpriteAsset IconTmp => null!;
+
///
/// Gets a value indicating whether the modifier is hidden on the UI. Will be hidden either way if no description is provided.
///
@@ -69,6 +195,11 @@ public abstract class BaseModifier : IOptionable
///
public virtual Color FreeplayFileColor => Color.gray;
+ ///
+ /// Gets the of the modifier, used in the wiki and other UI outside freeplay.
+ ///
+ public virtual Color GeneralColor => FreeplayFileColor;
+
///
/// Gets a value indicating whether the modifier is unique. If , the player can only have one instance of this modifier.
///
diff --git a/MiraAPI/Modifiers/Types/GameModifier.cs b/MiraAPI/Modifiers/Types/GameModifier.cs
index f574fd3..b432920 100644
--- a/MiraAPI/Modifiers/Types/GameModifier.cs
+++ b/MiraAPI/Modifiers/Types/GameModifier.cs
@@ -9,6 +9,9 @@ namespace MiraAPI.Modifiers.Types;
[MiraIgnore]
public abstract class GameModifier : BaseModifier
{
+ ///
+ public override bool? ForceShowModifierOnWiki => null;
+
///
public override bool ShowInFreeplay => true;