Decompiled source of WindRunDisplay v1.0.0

plugins/WindRunDisplay.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WindRunDisplay")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+eae49d2b72945c638dab65015478823d35e84431")]
[assembly: AssemblyProduct("WindRunDisplay")]
[assembly: AssemblyTitle("WindRunDisplay")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 WindRunDisplay
{
	[HarmonyPatch(typeof(Hud), "UpdateStatusEffects")]
	internal static class HudTextPatch
	{
		private struct Original
		{
			public bool AutoSize;

			public float FontSize;

			public TextWrappingModes Wrapping;

			public TextOverflowModes Overflow;

			public VerticalAlignmentOptions Vertical;
		}

		private static readonly Dictionary<TMP_Text, Original> Modified = new Dictionary<TMP_Text, Original>();

		private static bool _logged;

		private static readonly List<TMP_Text> Dead = new List<TMP_Text>();

		private static void Postfix(List<StatusEffect> statusEffects, List<RectTransform> ___m_statusEffects)
		{
			foreach (TMP_Text key in Modified.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					Dead.Add(key);
				}
			}
			foreach (TMP_Text item in Dead)
			{
				Modified.Remove(item);
			}
			Dead.Clear();
			int num = Mathf.Min(statusEffects.Count, ___m_statusEffects.Count);
			for (int i = 0; i < num; i++)
			{
				RectTransform val = ___m_statusEffects[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Transform val2 = ((Transform)val).Find("TimeText");
				TMP_Text val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<TMP_Text>() : null);
				if (!((Object)(object)val3 == (Object)null))
				{
					StatusEffect obj = statusEffects[i];
					SE_Stats val4 = (SE_Stats)(object)((obj is SE_Stats) ? obj : null);
					Original value;
					if (val4 != null && Plugin.IsWindRun(val4) && Plugin.IconFontSize.Value > 0f)
					{
						Apply(val3);
					}
					else if (Modified.TryGetValue(val3, out value))
					{
						Restore(val3, value);
					}
				}
			}
		}

		private static void Apply(TMP_Text text)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			if (!Modified.TryGetValue(text, out var value))
			{
				value = new Original
				{
					AutoSize = text.enableAutoSizing,
					FontSize = text.fontSize,
					Wrapping = text.textWrappingMode,
					Overflow = text.overflowMode,
					Vertical = text.verticalAlignment
				};
				Modified[text] = value;
				if (!_logged)
				{
					_logged = true;
					Rect rect = text.rectTransform.rect;
					Vector2 size = ((Rect)(ref rect)).size;
					Plugin.Log.LogInfo((object)($"Vanilla TimeText: autoSize={text.enableAutoSizing} fontSize={text.fontSize} " + $"min={text.fontSizeMin} max={text.fontSizeMax} wrap={text.textWrappingMode} " + $"overflow={text.overflowMode} align={text.alignment} rect={size.x}x{size.y}"));
				}
			}
			text.enableAutoSizing = false;
			text.fontSize = Plugin.IconFontSize.Value;
			text.textWrappingMode = (TextWrappingModes)0;
			text.overflowMode = (TextOverflowModes)0;
			text.verticalAlignment = (VerticalAlignmentOptions)256;
		}

		private static void Restore(TMP_Text text, Original orig)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			text.enableAutoSizing = orig.AutoSize;
			text.fontSize = orig.FontSize;
			text.textWrappingMode = orig.Wrapping;
			text.overflowMode = orig.Overflow;
			text.verticalAlignment = orig.Vertical;
			Modified.Remove(text);
		}

		internal static void RestoreAll()
		{
			foreach (KeyValuePair<TMP_Text, Original> item in new List<KeyValuePair<TMP_Text, Original>>(Modified))
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					Restore(item.Key, item.Value);
				}
			}
			Modified.Clear();
		}
	}
	public enum IconField
	{
		RunSpeed,
		RunStamina,
		Wind
	}
	public static class IconText
	{
		public const string Placeholder = "%s";

		public static List<IconField> ParseFields(string fields, List<string> unknown = null)
		{
			List<IconField> list = new List<IconField>();
			if (string.IsNullOrWhiteSpace(fields))
			{
				return list;
			}
			string[] array = fields.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0)
				{
					if (Enum.TryParse<IconField>(text, ignoreCase: true, out var result) && Enum.IsDefined(typeof(IconField), result))
					{
						list.Add(result);
					}
					else
					{
						unknown?.Add(text);
					}
				}
			}
			return list;
		}

		public static string Format(string format, string value)
		{
			if (string.IsNullOrEmpty(format))
			{
				return value;
			}
			if (!format.Contains("%s"))
			{
				return format + " " + value;
			}
			return format.Replace("%s", value);
		}
	}
	[HarmonyPatch(typeof(StatusEffect), "GetIconText")]
	internal static class IconTextPatch
	{
		private static void Postfix(StatusEffect __instance, ref string __result)
		{
			SE_Stats val = (SE_Stats)(object)((__instance is SE_Stats) ? __instance : null);
			if (val == null || !Plugin.IsWindRun(val) || (Object)(object)((StatusEffect)val).m_character == (Object)null || (Object)(object)((StatusEffect)val).m_character != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Plugin.Current(val, out var speed, out var stamina);
			List<string> list = new List<string>(4);
			if (!string.IsNullOrEmpty(__result))
			{
				list.Add(__result);
			}
			using (List<IconField>.Enumerator enumerator = Plugin.IconFields.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					switch (enumerator.Current)
					{
					case IconField.RunSpeed:
						if (val.m_windMovementModifier != 0f)
						{
							list.Add(IconText.Format(Plugin.RunSpeedFormat.Value, WindRunMath.Percent(speed)));
						}
						break;
					case IconField.RunStamina:
						if (val.m_windRunStaminaModifier != 0f)
						{
							list.Add(IconText.Format(Plugin.RunStaminaFormat.Value, WindRunMath.Percent(stamina)));
						}
						break;
					case IconField.Wind:
						if ((Object)(object)EnvMan.instance != (Object)null)
						{
							list.Add(IconText.Format(Plugin.WindFormat.Value, WindRunMath.Magnitude(EnvMan.instance.GetWindIntensity())));
						}
						break;
					}
				}
			}
			__result = string.Join("\n", list);
		}
	}
	[HarmonyPatch(typeof(SE_Stats), "GetTooltipString")]
	internal static class TooltipPatch
	{
		private static void Postfix(SE_Stats __instance, ref string __result)
		{
			if (Plugin.ExtendTooltip.Value && Plugin.IsWindRun(__instance))
			{
				bool flag = (Object)(object)((StatusEffect)__instance).m_character != (Object)null && (Object)(object)((StatusEffect)__instance).m_character == (Object)(object)Player.m_localPlayer;
				float speed = 0f;
				float stamina = 0f;
				if (flag)
				{
					Plugin.Current(__instance, out speed, out stamina);
				}
				if (__instance.m_windMovementModifier != 0f)
				{
					__result += Line("Wind run speed", __instance.m_windMovementModifier, flag, speed);
				}
				if (__instance.m_windRunStaminaModifier != 0f)
				{
					__result += Line("Wind run stamina", __instance.m_windRunStaminaModifier, flag, stamina);
				}
			}
		}

		private static string Line(string label, float max, bool live, float now)
		{
			string text = label + ": up to <color=orange>" + WindRunMath.Percent(max) + "</color>";
			if (live)
			{
				text = text + " (now <color=orange>" + WindRunMath.Percent(now) + "</color>)";
			}
			return text + "\n";
		}
	}
	[BepInPlugin("surxe.WindRunDisplay", "Wind Run Display", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "surxe.WindRunDisplay";

		public const string Name = "Wind Run Display";

		public const string Version = "1.0.0";

		internal static ConfigEntry<string> Fields;

		internal static ConfigEntry<string> RunSpeedFormat;

		internal static ConfigEntry<string> RunStaminaFormat;

		internal static ConfigEntry<string> WindFormat;

		internal static ConfigEntry<float> IconFontSize;

		internal static ConfigEntry<bool> ExtendTooltip;

		internal static List<IconField> IconFields = new List<IconField>();

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Fields = ((BaseUnityPlugin)this).Config.Bind<string>("Icon", "Fields", "RunSpeed", "Lines shown under the Wind run icon, top to bottom, comma-separated. Available: RunSpeed (speed bonus), RunStamina (run stamina reduction), Wind (wind intensity, independent of direction). Empty = no text.");
			RunSpeedFormat = ((BaseUnityPlugin)this).Config.Bind<string>("Icon", "RunSpeedFormat", "Speed: %s", "Label for the RunSpeed line. '%s' is replaced by the value.");
			RunStaminaFormat = ((BaseUnityPlugin)this).Config.Bind<string>("Icon", "RunStaminaFormat", "Run stamina: %s", "Label for the RunStamina line. '%s' is replaced by the value.");
			WindFormat = ((BaseUnityPlugin)this).Config.Bind<string>("Icon", "WindFormat", "Wind: %s", "Label for the Wind line. '%s' is replaced by the value.");
			IconFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("Icon", "IconFontSize", 0f, "0 = leave the game's text box as is (its own size; it auto-shrinks longer or multi-line text). Above 0 = use this fixed font size, with no shrinking and the lines extending below the icon.");
			ExtendTooltip = ((BaseUnityPlugin)this).Config.Bind<bool>("Tooltip", "ExtendTooltip", true, "Append max/current Wind run speed and stamina values to the status effect tooltip.");
			ParseFields();
			Fields.SettingChanged += delegate
			{
				ParseFields();
			};
			_harmony = new Harmony("surxe.WindRunDisplay");
			_harmony.PatchAll(typeof(Plugin).Assembly);
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			HudTextPatch.RestoreAll();
		}

		private static void ParseFields()
		{
			List<string> list = new List<string>();
			IconFields = IconText.ParseFields(Fields.Value, list);
			if (list.Count > 0)
			{
				Log.LogWarning((object)("Ignoring unknown Fields entries: " + string.Join(", ", list) + " (available: " + string.Join(", ", Enum.GetNames(typeof(IconField))) + ")"));
			}
		}

		internal static Vector3 PreviewDir(Character character)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 moveDir = character.GetMoveDir();
			if (((Vector3)(ref moveDir)).sqrMagnitude > 0.01f)
			{
				return ((Vector3)(ref moveDir)).normalized;
			}
			GameCamera instance = GameCamera.instance;
			Vector3 val = (((Object)(object)instance != (Object)null) ? ((Component)instance).transform.forward : ((Component)character).transform.forward);
			val.y = 0f;
			if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f))
			{
				return Vector3.forward;
			}
			return ((Vector3)(ref val)).normalized;
		}

		internal static bool IsWindRun(SE_Stats se)
		{
			if (se.m_windMovementModifier == 0f)
			{
				return se.m_windRunStaminaModifier != 0f;
			}
			return true;
		}

		internal static void Current(SE_Stats se, out float speed, out float stamina)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)((StatusEffect)se).m_character == (Object)null)
			{
				speed = 0f;
				stamina = 0f;
				return;
			}
			float dot = Vector3.Dot(PreviewDir(((StatusEffect)se).m_character), instance.GetWindDir());
			float windIntensity = instance.GetWindIntensity();
			speed = WindRunMath.Factor(dot, windIntensity, se.m_windMovementModifier);
			stamina = WindRunMath.Factor(dot, windIntensity, se.m_windRunStaminaModifier);
		}
	}
	public static class WindRunMath
	{
		public static float Factor(float dot, float windIntensity, float modifier)
		{
			return (dot + 1f) / 2f * windIntensity * modifier;
		}

		public static string Percent(float factor)
		{
			int num = (int)Math.Round(factor * 100f, MidpointRounding.AwayFromZero);
			return ((num < 0) ? "-" : "+") + Math.Abs(num) + "%";
		}

		public static string Magnitude(float value)
		{
			return (int)Math.Round(value * 100f, MidpointRounding.AwayFromZero) + "%";
		}
	}
}