Decompiled source of CrossHair v1.0.0

BepInEx/plugins/com.ctnoriginals.crosshair.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
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 CrossHair.Utilities;
using GameNetcodeStuff;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.ctnoriginals.crosshair")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Adds a CrossHair to the center of your screen to indicate where you are aiming.")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("CrossHair")]
[assembly: AssemblyTitle("com.ctnoriginals.crosshair")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CrossHair
{
	[BepInPlugin("com.ctnoriginals.crosshair", "CrossHair", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("com.ctnoriginals.crosshair");

		public static ConfigFile Config = new ConfigFile(Paths.ConfigPath + "\\com.ctnoriginals.crosshair.cfg", true);

		public static ConfigEntry<string> CrossHairText;

		public static ConfigEntry<float> CrossHairSize;

		public static ConfigEntry<bool> CrossHairShadow;

		public static ConfigEntry<string> CrossHairColor;

		public static ConfigEntry<int> CrossHairOpacity;

		public static ConfigEntry<bool> CrossHairFading;

		public static ManualLogSource CLog;

		public static bool DebugMode = false;

		private void Awake()
		{
			CLog = ((BaseUnityPlugin)this).Logger;
			CLog.LogInfo((object)("Plugin com.ctnoriginals.crosshair is loaded! Version: 1.1.1 (" + (DebugMode ? "Debug" : "Release") + ")"));
			ConfigFile();
			harmony.PatchAll();
		}

		private void ConfigFile()
		{
			CrossHairText = Config.Bind<string>("!General", "CrossHairText", "-  +  -", "Text to display as crosshair (use \\n for new line)");
			CrossHairSize = Config.Bind<float>("!General", "CrossHairSize", 50f, "Size of the crosshair");
			CrossHairShadow = Config.Bind<bool>("!General", "CrossHairShadow", true, "Whether to display a shadow behind the crosshair");
			CrossHairColor = Config.Bind<string>("Appearance", "CrossHairColor", "ffffff", "Color of the crosshair in hexadecimal (Do not include the #)");
			CrossHairOpacity = Config.Bind<int>("Appearance", "CrossHairOpacity", 80, "Opacity of the crosshair (0 to 100)%");
			CrossHairFading = Config.Bind<bool>("Appearance", "CrossHairFading", true, "Whether the crosshair should fade in and out in specific situations");
			CrossHair.Utilities.Console.LogMessage("CrossHairText: " + CrossHairText.Value);
			CrossHair.Utilities.Console.LogMessage($"CrossHairSize: {CrossHairSize.Value}");
			CrossHair.Utilities.Console.LogMessage($"CrossHairShadow: {CrossHairShadow.Value}");
			CrossHair.Utilities.Console.LogMessage("CrossHairColor: " + CrossHairColor.Value);
			CrossHair.Utilities.Console.LogMessage($"CrossHairOpacity: {CrossHairOpacity.Value}");
			CrossHair.Utilities.Console.LogMessage($"CrossHairFading: {CrossHairFading.Value}");
			Config.Save();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.ctnoriginals.crosshair";

		public const string PLUGIN_NAME = "CrossHair";

		public const string PLUGIN_VERSION = "1.1.1";
	}
}
namespace CrossHair.Utilities
{
	public static class Console
	{
		public static void Log(string message)
		{
			SendLog(message, "Log");
		}

		public static void LogInfo(string message)
		{
			SendLog(message, "LogInfo");
		}

		public static void LogError(string message)
		{
			SendLog(message, "LogError");
		}

		public static void LogWarning(string message)
		{
			SendLog(message, "LogWarning");
		}

		public static void LogDebug(string message)
		{
			SendLog(message, "LogDebug");
		}

		public static void LogFatal(string message)
		{
			SendLog(message, "LogFatal");
		}

		public static void LogMessage(string message)
		{
			SendLog(message, "LogMessage");
		}

		private static void SendLog(string message, string level = null)
		{
			if (!Plugin.DebugMode && (level == "LogDebug" || level == "LogInfo"))
			{
				return;
			}
			switch (level)
			{
			case "LogInfo":
				Plugin.CLog.LogInfo((object)message);
				return;
			case "LogError":
				Plugin.CLog.LogError((object)message);
				return;
			case "LogWarning":
				Plugin.CLog.LogWarning((object)message);
				return;
			case "LogDebug":
				Plugin.CLog.LogDebug((object)message);
				return;
			case "LogFatal":
				Plugin.CLog.LogFatal((object)message);
				return;
			case "LogMessage":
				Plugin.CLog.LogMessage((object)message);
				return;
			}
			if (level != "Log")
			{
				Debug.Log((object)("[" + level + "]: " + message));
			}
			else
			{
				Debug.Log((object)message);
			}
		}
	}
	public class PrivateFieldAccessor<InstanceType>
	{
		private FieldInfo _field;

		private object _instance;

		public PrivateFieldAccessor(object instance, string fieldname)
		{
			_field = typeof(InstanceType).GetField(fieldname, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_instance = instance;
		}

		public T Get<T>()
		{
			return Utils.GetInstanceField<T>(_instance, _field.Name);
		}

		public void Set<T>(T value)
		{
			_field.SetValue(_instance, value);
		}
	}
	internal static class Utils
	{
		public static T GetInstanceField<T>(object instance, string fieldName)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			return (T)instance.GetType().GetField(fieldName, bindingAttr).GetValue(instance);
		}
	}
}
namespace CrossHair.Patches
{
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDManagerPatch
	{
		public static Transform CrossHair;

		public static TextMeshProUGUI CrossHairTMP;

		public static float CrossHairAlpha = 200f;

		public static Transform CrossHairShadow;

		public static float CrossHairShadowAlpha = 100f;

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start(ref HUDManager __instance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			CrossHair = ((TMP_Text)Object.Instantiate<TextMeshProUGUI>(new GameObject().AddComponent<TextMeshProUGUI>())).transform;
			global::CrossHair.Utilities.Console.LogDebug(((Object)CrossHair).name ?? "");
			((Object)CrossHair).name = "CrossHair";
			Transform transform = ((Component)((Component)__instance.PTTIcon).transform.parent.parent.parent.Find("PlayerCursor").Find("Cursor")).transform;
			CrossHairTMP = ((Component)CrossHair).GetComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)CrossHairTMP).rectTransform;
			((Transform)rectTransform).SetParent(transform, false);
			rectTransform.anchoredPosition = new Vector2(0f, 0f);
			((Transform)rectTransform).localPosition = new Vector3(0f, 0f, 0f);
			rectTransform.offsetMin = new Vector2(-500f, -500f);
			rectTransform.offsetMax = new Vector2(500f, 500f);
			string text = Plugin.CrossHairColor.Value;
			if (text.Length != 6)
			{
				text = HexFormatException("character amount: \"" + text + "\"");
			}
			int num = 16777215;
			try
			{
				num = int.Parse(text.Replace("#", ""), NumberStyles.HexNumber);
			}
			catch (FormatException)
			{
				num = int.Parse(HexFormatException("color: \"" + text + "\""), NumberStyles.HexNumber);
			}
			Color color = Color.FromArgb(num);
			CrossHairAlpha = (int)(byte)(Plugin.CrossHairOpacity.Value * 255 / 100);
			CrossHairShadowAlpha = (int)(byte)(CrossHairAlpha * 50f / 100f);
			((TMP_Text)CrossHairTMP).text = Plugin.CrossHairText.Value;
			((TMP_Text)CrossHairTMP).fontSize = Plugin.CrossHairSize.Value;
			((Graphic)CrossHairTMP).color = Color32.op_Implicit(new Color32(color.R, color.G, color.B, (byte)Mathf.RoundToInt(CrossHairAlpha)));
			global::CrossHair.Utilities.Console.LogDebug($"CrossHairColor: ({color.R}, {color.G}, {color.B}, {CrossHairAlpha})");
			((TMP_Text)CrossHairTMP).alignment = (TextAlignmentOptions)514;
			((TMP_Text)CrossHairTMP).font = ((TMP_Text)__instance.controlTipLines[0]).font;
			((Behaviour)CrossHairTMP).enabled = true;
			if (Plugin.CrossHairShadow.Value)
			{
				CrossHairShadow = Object.Instantiate<Transform>(CrossHair, transform);
				TextMeshProUGUI component = ((Component)CrossHairShadow).GetComponent<TextMeshProUGUI>();
				((Object)CrossHairShadow).name = "CrossHairShadow";
				((TMP_Text)component).fontSize = Plugin.CrossHairSize.Value;
				((Graphic)component).color = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)CrossHairShadowAlpha));
				((Transform)((TMP_Text)component).rectTransform).localPosition = new Vector3(2f, -2f, 0f);
				((Transform)rectTransform).SetAsLastSibling();
			}
		}

		public static void SetCrossHairAlphaPercent(float target)
		{
			if (Object.op_Implicit((Object)(object)CrossHair))
			{
				((TMP_Text)((Component)CrossHair).GetComponent<TextMeshProUGUI>()).alpha = target * (CrossHairAlpha / 255f);
				if (Object.op_Implicit((Object)(object)CrossHairShadow))
				{
					((TMP_Text)((Component)CrossHairShadow).GetComponent<TextMeshProUGUI>()).alpha = target * (CrossHairShadowAlpha / 255f);
				}
			}
		}

		private static string HexFormatException(string message = "color")
		{
			global::CrossHair.Utilities.Console.LogMessage("Invalid hex " + message + ", using default color (ffffff)");
			Plugin.CrossHairColor.Value = "ffffff";
			Plugin.Config.Save();
			return "ffffff";
		}
	}
	public class TargetFieldHook
	{
		public string fieldName;

		public object targetValue;

		private float fadeValue;

		private float fadeOutDuration;

		private float fadeInDuration;

		public PrivateFieldAccessor<PlayerControllerB> field;

		private bool isFading;

		public float currentFade = 1f;

		private float fadeTimer;

		public TargetFieldHook(PlayerControllerB playerInstance, string fieldName, object targetValue, float fadeValue = 0.2f, float fadeOutDuration = 0.2f, float fadeInDuration = 0.5f)
		{
			this.fieldName = fieldName;
			this.targetValue = targetValue;
			this.fadeValue = fadeValue;
			this.fadeOutDuration = fadeOutDuration;
			this.fadeInDuration = fadeInDuration;
			field = new PrivateFieldAccessor<PlayerControllerB>(playerInstance, fieldName);
		}

		public bool GetState()
		{
			object obj = field.Get<object>();
			try
			{
				object obj2 = targetValue;
				InteractTrigger val = (InteractTrigger)((obj2 is InteractTrigger) ? obj2 : null);
				if (val == null)
				{
					if (!(obj2 is bool flag))
					{
						if (!(obj2 is float num))
						{
							if (!(obj2 is int num2))
							{
								if (obj2 is string text)
								{
									return (string)obj == text;
								}
								throw new TypeAccessException($"TargetFieldHook.GetState() - Unknown type: {targetValue.GetType()}");
							}
							return (int)obj == num2;
						}
						return (float)obj == num;
					}
					return (bool)obj == flag;
				}
				return obj != null == Object.op_Implicit((Object)(object)val);
			}
			catch (TypeAccessException ex)
			{
				CrossHair.Utilities.Console.LogError(ex.ToString());
			}
			CrossHair.Utilities.Console.LogDebug($"{fieldName} - Unknown type: {targetValue.GetType()}");
			return false;
		}

		public void Update()
		{
			if (isFading)
			{
				if (!GetState())
				{
					isFading = false;
					fadeTimer = currentFade;
				}
				else if (currentFade > fadeValue)
				{
					currentFade = Mathf.Lerp(1f, fadeValue, fadeTimer);
					fadeTimer += Time.deltaTime / fadeOutDuration;
				}
			}
			else if (GetState())
			{
				isFading = true;
				fadeTimer = 1f - currentFade;
			}
			else if (currentFade < 1f)
			{
				currentFade = Mathf.Lerp(fadeValue, 1f, fadeTimer);
				fadeTimer += Time.deltaTime / fadeInDuration;
			}
			currentFade = Mathf.Clamp(currentFade, 0f, 1f);
			fadeTimer = Mathf.Clamp(fadeTimer, 0f, 1f);
		}

		public void LogValues()
		{
			CrossHair.Utilities.Console.LogDebug($"{fieldName}\nValue: {field.Get<object>()} - Target: {targetValue}\nFade: {fadeValue} - Duration: {fadeOutDuration} - {fadeInDuration}");
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerBPatch
	{
		private static List<TargetFieldHook> targetFields = new List<TargetFieldHook>();

		[HarmonyPatch("ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		private static void ConnectClientToPlayerObject(ref PlayerControllerB __instance)
		{
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (!((Object)(object)__instance != (Object)(object)localPlayerController))
			{
				CrossHair.Utilities.Console.LogInfo("PlayerControllerB.ConnectClientToPlayerObject() called");
				if (Plugin.CrossHairFading.Value)
				{
					targetFields = new List<TargetFieldHook>
					{
						new TargetFieldHook(__instance, "isWalking", true, 0.5f, 1f, 0.25f),
						new TargetFieldHook(__instance, "isSprinting", true, 0.25f, 0.5f, 0.25f),
						new TargetFieldHook(__instance, "isJumping", true, 0.1f, 0.05f, 1f),
						new TargetFieldHook(__instance, "isFallingFromJump", true, 0.1f, 0.01f, 1f),
						new TargetFieldHook(__instance, "isFallingNoJump", true, 0.1f, 0.01f, 1f),
						new TargetFieldHook(__instance, "isCrouching", true, 0.5f, 0.5f, 1f),
						new TargetFieldHook(__instance, "isClimbingLadder", true, 0.01f, 0.25f, 2f),
						new TargetFieldHook(__instance, "twoHanded", true, 0.1f, 0.01f),
						new TargetFieldHook(__instance, "performingEmote", true, 0.05f, 0.2f, 2f),
						new TargetFieldHook(__instance, "isUnderwater", true, 0.025f, 0.1f, 1f),
						new TargetFieldHook(__instance, "inTerminalMenu", true, 0f, 0.2f, 1.5f),
						new TargetFieldHook(__instance, "isPlayerDead", true, 0.05f, 2.5f, 1f),
						new TargetFieldHook(__instance, "hasBegunSpectating", true, 0f, 5f, 50f),
						new TargetFieldHook(__instance, "isHoldingInteract", true, 0.1f, 0.5f)
					};
					CrossHair.Utilities.Console.LogDebug($"PlayerControllerB.targetFields.Count: {targetFields.Count}");
				}
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update(ref PlayerControllerB __instance)
		{
			if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController)
			{
				return;
			}
			float num = 1f;
			foreach (TargetFieldHook targetField in targetFields)
			{
				targetField.Update();
				if (targetField.currentFade < num)
				{
					num = targetField.currentFade;
					_ = targetField.fieldName;
				}
			}
			if (Mathf.Abs(((TMP_Text)HUDManagerPatch.CrossHairTMP).alpha - num * (HUDManagerPatch.CrossHairAlpha / 255f)) > 0.0001f)
			{
				HUDManagerPatch.SetCrossHairAlphaPercent(num);
			}
		}
	}
}