The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of Numberry v0.1.2
plugins/com.github.bkolacinski.numberry.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.bkolacinski")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © bkolacinski 2025")] [assembly: AssemblyDescription("Displays numerical values on stamina, bonus stamina, and affliction bars with extensive customization options.")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2+d517eb109368d4c7210d8451bc9a9e4d01fca1f9")] [assembly: AssemblyProduct("Numberry")] [assembly: AssemblyTitle("Numberry")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Numberry { [BepInPlugin("com.github.bkolacinski.numberry", "Numberry", "0.1.2")] public class Plugin : BaseUnityPlugin { [HarmonyPatch] internal static class StaminaBar_Patches { [HarmonyPatch(typeof(StaminaBar), "Update")] [HarmonyPostfix] private static void UpdatePostfix(StaminaBar __instance) { try { if (!InitializedBars.ContainsKey(__instance) || !InitializedBars[__instance]) { InitializeBars(__instance); InitializedBars[__instance] = true; } UpdateAllTexts(__instance); } catch (Exception arg) { Log.LogError((object)$"Error in StaminaBar.Update patch: {arg}"); if ((Object)(object)__instance != (Object)null && !InitializedBars.ContainsKey(__instance)) { InitializedBars[__instance] = true; } } } } private static Plugin _instance = null; private static TMP_FontAsset _gameFont = null; private static ConfigEntry<int> _fontSize = null; private static ConfigEntry<float> _outlineWidth = null; private static ConfigEntry<string> _textColorHex = null; private static ConfigEntry<string> _outlineColorHex = null; private static ConfigEntry<float> _textOffsetY = null; private static ConfigEntry<float> _fontWidthScale = null; private static ConfigEntry<float> _valueDivisor = null; private static ConfigEntry<bool> _displayStaminaValue = null; private static ConfigEntry<bool> _displayBonusStaminaValue = null; private static ConfigEntry<bool> _displayBonusAsInteger = null; private static ConfigEntry<float> _bonusTextOffsetY = null; private static Color _textColorValue; private static Color _outlineColorValue; private static readonly Dictionary<StaminaBar, bool> InitializedBars = new Dictionary<StaminaBar, bool>(); private static readonly Dictionary<string, TextMeshProUGUI> BarTexts = new Dictionary<string, TextMeshProUGUI>(); private static readonly Dictionary<string, float> LastKnownValues = new Dictionary<string, float>(); private static readonly Dictionary<StaminaBar, float> MaxBonusWidths = new Dictionary<StaminaBar, float>(); public const string Id = "com.github.bkolacinski.numberry"; internal static ManualLogSource Log { get; private set; } = null; public static string Name => "Numberry"; public static string Version => "0.1.2"; private void Awake() { //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown _instance = this; Log = ((BaseUnityPlugin)this).Logger; _fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "FontSize", 24, "Font size."); _outlineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "OutlineWidth", 0.125f, "Outline width (0-1). Lower value gives a thinner outline."); _textColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "TextColor", "#FFFFFF", "Text color."); _outlineColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "OutlineColor", "#000000", "Outline color."); _textOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "TextOffsetY", 3.5f, "Text vertical offset (up/down)."); _fontWidthScale = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "FontWidthScale", 1.1f, "Font width scale (horizontal stretch, e.g. 1.1 for 110% width)."); _valueDivisor = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "ValueDivisor", 15f, "Divisor for converting UI width to stamina/bonus/affliction units (wiki uses 6, this mode uses 15)."); _displayStaminaValue = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "DisplayStamina", true, "Display raw stamina value."); _displayBonusStaminaValue = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "DisplayBonusStaminaValue", true, "Display bonus stamina value."); _displayBonusAsInteger = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "DisplayBonusAsInteger", true, "Display bonus stamina as integer (true) or with one decimal (false)."); _bonusTextOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "BonusTextOffsetY", _textOffsetY.Value, "Bonus text vertical offset."); ColorUtility.TryParseHtmlString(_textColorHex.Value, ref _textColorValue); ColorUtility.TryParseHtmlString(_outlineColorHex.Value, ref _outlineColorValue); Harmony val = new Harmony("com.peakmodding.peakmod"); val.PatchAll(typeof(StaminaBar_Patches)); } private static void InitializeBars(StaminaBar sb) { Log.LogInfo((object)$"Initializing stamina info text objects for StaminaBar {((Object)sb).GetInstanceID()}."); TextMeshProUGUI[] componentsInChildren = ((Component)sb).GetComponentsInChildren<TextMeshProUGUI>(); foreach (TextMeshProUGUI val in componentsInChildren) { if (((Object)val).name.EndsWith("ValueText")) { Object.Destroy((Object)(object)((Component)val).gameObject); } } if ((Object)(object)_gameFont == (Object)null) { _gameFont = ((TMP_Text)GameObject.Find("GAME/GUIManager").GetComponent<GUIManager>().heroDayText).font; } if (_displayStaminaValue.Value) { FieldInfo field = ((object)sb).GetType().GetField("staminaBar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(sb); Component val2 = (Component)((value is Component) ? value : null); if (val2 != null) { CreateTextObject(((Component)val2.transform.parent).gameObject, $"Stamina_{((Object)sb).GetInstanceID()}", _textOffsetY.Value); goto IL_0103; } } Log.LogWarning((object)"Could not find 'staminaBar' to attach stamina text."); } goto IL_0103; IL_0103: if (_displayBonusStaminaValue.Value) { FieldInfo field2 = ((object)sb).GetType().GetField("extraBarStamina", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { object? value2 = field2.GetValue(sb); Component val3 = (Component)((value2 is Component) ? value2 : null); if (val3 != null) { CreateTextObject(val3.gameObject, $"BonusStamina_{((Object)sb).GetInstanceID()}", _bonusTextOffsetY.Value); goto IL_017c; } } Log.LogWarning((object)"Could not find 'extraBarStamina' to attach bonus stamina text."); } goto IL_017c; IL_017c: BarAffliction[] componentsInChildren2 = ((Component)sb).GetComponentsInChildren<BarAffliction>(true); BarAffliction[] array = componentsInChildren2; foreach (BarAffliction val4 in array) { CreateTextObject(((Component)val4).gameObject, $"Affliction_{((Object)val4).GetInstanceID()}", _textOffsetY.Value); } Log.LogInfo((object)$"Finished initializing stamina info text objects for StaminaBar {((Object)sb).GetInstanceID()}."); } private static void CreateTextObject(GameObject parent, string key, float yOffset) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(key + "_ValueText", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent.transform, false); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = _gameFont; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((Graphic)val2).color = _textColorValue; ((TMP_Text)val2).fontSize = _fontSize.Value; Material val3 = Object.Instantiate<Material>(((TMP_Text)val2).fontSharedMaterial); val3.SetFloat(ShaderUtilities.ID_OutlineWidth, _outlineWidth.Value); val3.SetColor(ShaderUtilities.ID_OutlineColor, _outlineColorValue); val3.EnableKeyword("OUTLINE_ON"); ((TMP_Text)val2).fontMaterial = val3; ((Graphic)val2).raycastTarget = false; RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; component.anchoredPosition = new Vector2(0f, yOffset); val.transform.localScale = new Vector3(_fontWidthScale.Value, 1f, 1f); BarTexts[key] = val2; LastKnownValues[key] = -1f; ((Component)val2).gameObject.SetActive(false); } private static void UpdateAllTexts(StaminaBar sb) { //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) string key = $"Stamina_{((Object)sb).GetInstanceID()}"; if (_displayStaminaValue.Value && BarTexts.ContainsKey(key)) { FieldInfo field = ((object)sb).GetType().GetField("desiredStaminaSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { float rawValue = (float)field.GetValue(sb); UpdateText(key, rawValue, showDecimal: false); } } string key2 = $"BonusStamina_{((Object)sb).GetInstanceID()}"; if (_displayBonusStaminaValue.Value && BarTexts.ContainsKey(key2)) { FieldInfo field2 = ((object)sb).GetType().GetField("desiredExtraStaminaSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field3 = ((object)sb).GetType().GetField("extraBarStamina", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field4 = ((object)sb).GetType().GetField("desiredStaminaSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null && field3 != null && field4 != null) { float num = (float)field2.GetValue(sb); float num2 = (float)field4.GetValue(sb); object? value = field3.GetValue(sb); Component val = (Component)((value is Component) ? value : null); RectTransform val2 = ((val != null) ? val.GetComponent<RectTransform>() : null); if ((Object)(object)val2 != (Object)null && BarTexts.TryGetValue(key2, out TextMeshProUGUI value2)) { RectTransform component = ((Component)value2).GetComponent<RectTransform>(); LastKnownValues.TryGetValue(key2, out var value3); bool flag = num < value3; if (num2 < 0.01f && flag) { Rect rect; if (!MaxBonusWidths.ContainsKey(sb)) { Dictionary<StaminaBar, float> maxBonusWidths = MaxBonusWidths; rect = val2.rect; maxBonusWidths[sb] = ((Rect)(ref rect)).width; } float num3 = MaxBonusWidths[sb]; rect = val2.rect; if (((Rect)(ref rect)).width > num3) { rect = val2.rect; num3 = ((Rect)(ref rect)).width; MaxBonusWidths[sb] = num3; } rect = val2.rect; float width = ((Rect)(ref rect)).width; float num4 = (num3 - width) / 2f; component.anchoredPosition = new Vector2(num4, _bonusTextOffsetY.Value); } else { MaxBonusWidths.Remove(sb); component.anchoredPosition = new Vector2(0f, _bonusTextOffsetY.Value); } UpdateText(key2, num, !_displayBonusAsInteger.Value); } else { UpdateText(key2, num, !_displayBonusAsInteger.Value); } } } BarAffliction[] componentsInChildren = ((Component)sb).GetComponentsInChildren<BarAffliction>(true); BarAffliction[] array = componentsInChildren; foreach (BarAffliction val3 in array) { string key3 = $"Affliction_{((Object)val3).GetInstanceID()}"; if (BarTexts.ContainsKey(key3)) { UpdateText(key3, val3.size, showDecimal: false); } } } private static void UpdateText(string key, float rawValue, bool showDecimal) { if (!BarTexts.TryGetValue(key, out TextMeshProUGUI value) || !LastKnownValues.TryGetValue(key, out var value2)) { return; } if ((Object)(object)value == (Object)null) { BarTexts.Remove(key); LastKnownValues.Remove(key); } else if (!Mathf.Approximately(rawValue, value2)) { LastKnownValues[key] = rawValue; float num = rawValue / _valueDivisor.Value; if (showDecimal ? (num > 0.5f) : (num >= 1f)) { ((TMP_Text)value).text = (showDecimal ? num.ToString("F1") : Mathf.FloorToInt(num).ToString()); ((Component)value).gameObject.SetActive(true); } else { ((Component)value).gameObject.SetActive(false); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }