Decompiled source of Numberry v0.1.2

plugins/com.github.bkolacinski.numberry.dll

Decompiled 2 months ago
using 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)
		{
		}
	}
}