Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CrossHair v1.1.2
BepInEx/plugins/com.ctnoriginals.crosshair.dll
Decompiled 2 years agousing 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); } } } }