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 BetterCrosshair v1.1.0
Dupo_BetterCrosshair.dll
Decompiled a week agousing System; 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 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("Dupo_BetterCrosshair")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+3649bdebbbbca951d381b70f322acadcbafe5166")] [assembly: AssemblyProduct("Dupo_BetterCrosshair")] [assembly: AssemblyTitle("Dupo_BetterCrosshair")] [assembly: AssemblyVersion("1.1.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 Dupo.BetterCrosshair { [BepInPlugin("dupo.BetterCrosshair", "Dupo_BetterCrosshair", "1.1.0")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "dupo.BetterCrosshair"; public const string ModName = "Dupo_BetterCrosshair"; public const string ModVersion = "1.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> RangedOnly; internal static ConfigEntry<bool> DebugLog; internal static ConfigEntry<CrosshairShape> Shape; internal static ConfigEntry<int> Size; internal static ConfigEntry<int> Thickness; internal static ConfigEntry<int> Gap; internal static ConfigEntry<int> DotSize; internal static ConfigEntry<int> OutlineThickness; internal static ConfigEntry<Color> FillColor; internal static ConfigEntry<Color> OutlineColor; internal static ConfigEntry<bool> TargetColors; internal static ConfigEntry<Color> EnemyColor; internal static ConfigEntry<Color> InteractColor; internal static ConfigEntry<float> EnemyRange; internal static ConfigEntry<bool> ChargeFeedback; internal static ConfigEntry<float> ChargeStartScale; internal static ConfigEntry<Color> ChargedColor; internal static bool SpriteDirty = true; private readonly Harmony _harmony = new Harmony("dupo.BetterCrosshair"); private void Awake() { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_0346: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Replace the vanilla crosshair with the BetterCrosshair one."); RangedOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Ranged Weapons Only", false, "Show the BetterCrosshair crosshair only while a ranged weapon (bow, crossbow, staff, wand) is equipped. Otherwise the vanilla crosshair is shown."); DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Debug Log", false, "Write extra diagnostic lines to BepInEx/LogOutput.log."); Shape = ((BaseUnityPlugin)this).Config.Bind<CrosshairShape>("2 - Shape", "Shape", CrosshairShape.CrossAndDot, "Crosshair shape."); Size = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Shape", "Size", 28, new ConfigDescription("Total width/height of the crosshair, in UI pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 128), Array.Empty<object>())); Thickness = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Shape", "Thickness", 3, new ConfigDescription("Thickness of the cross arms and of the circle line, in UI pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 16), Array.Empty<object>())); Gap = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Shape", "Gap", 5, new ConfigDescription("Empty space between the center and the start of each cross arm, in UI pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 64), Array.Empty<object>())); DotSize = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Shape", "Dot Size", 3, new ConfigDescription("Diameter of the center dot, in UI pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 32), Array.Empty<object>())); OutlineThickness = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Shape", "Outline Thickness", 2, new ConfigDescription("Thickness of the dark outline around the crosshair, in UI pixels. 0 = no outline.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 8), Array.Empty<object>())); FillColor = ((BaseUnityPlugin)this).Config.Bind<Color>("3 - Colors", "Color", new Color(1f, 0f, 1f, 1f), "Crosshair color (RRGGBBAA)."); OutlineColor = ((BaseUnityPlugin)this).Config.Bind<Color>("3 - Colors", "Outline Color", new Color(0f, 0f, 0f, 1f), "Outline color (RRGGBBAA). A dark outline keeps the crosshair visible on snow and bright effects."); TargetColors = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Target", "Target Colors", true, "Change the crosshair color when aiming at an enemy or at something you can interact with."); EnemyColor = ((BaseUnityPlugin)this).Config.Bind<Color>("4 - Target", "Enemy Color", new Color(1f, 0.15f, 0.15f, 1f), "Crosshair color when aiming at a living enemy (RRGGBBAA)."); InteractColor = ((BaseUnityPlugin)this).Config.Bind<Color>("4 - Target", "Interact Color", new Color(1f, 0.85f, 0f, 1f), "Crosshair color when aiming at something you can interact with: door, chest, item, workbench... (RRGGBBAA). Uses the game's own interaction range."); EnemyRange = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Target", "Enemy Range", 100f, new ConfigDescription("Maximum distance, in meters, at which an enemy under the crosshair is detected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 300f), Array.Empty<object>())); ChargeFeedback = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Charge", "Charge Feedback", true, "While drawing a bow, the crosshair shrinks to its normal size. When the bow is fully drawn, or a crossbow is loaded, the outline turns to Charged Color."); ChargeStartScale = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Charge", "Charge Start Scale", 1.75f, new ConfigDescription("Crosshair scale when you start drawing a bow. 1 = no shrinking.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>())); ChargedColor = ((BaseUnityPlugin)this).Config.Bind<Color>("5 - Charge", "Charged Color", new Color(0f, 1f, 0.2f, 1f), "Outline color when a bow is fully drawn or a crossbow is loaded (RRGGBBAA)."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { SpriteDirty = true; }; _harmony.PatchAll(typeof(HudPatches)); Log.LogInfo((object)"Dupo_BetterCrosshair 1.1.0 loaded"); } private void OnDestroy() { _harmony.UnpatchSelf(); } internal static void Debug(string message) { if (DebugLog.Value) { Log.LogInfo((object)message); } } internal static bool HasRangedWeapon(Player player) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon?.m_shared == null) { return false; } SkillType skillType = currentWeapon.m_shared.m_skillType; if (skillType - 8 <= 2 || (int)skillType == 14) { return true; } Attack attack = currentWeapon.m_shared.m_attack; if (attack != null) { if (!attack.m_bowDraw) { return (int)attack.m_attackType == 2; } return true; } return false; } internal static bool IsReloadWeaponLoaded(Player player) { Attack val = ((Humanoid)player).GetCurrentWeapon()?.m_shared?.m_attack; if (val != null && val.m_requiresReload) { return ((Humanoid)player).IsWeaponLoaded(); } return false; } } public enum CrosshairShape { Cross, CrossAndDot, Dot, Circle, CircleAndDot } internal enum TargetKind { None, Interactable, Enemy } [HarmonyPatch] internal static class HudPatches { private static RectTransform _root; private static Image _outline; private static Image _fill; private static Texture2D _outlineTex; private static Texture2D _fillTex; private static TargetKind _lastTarget; private static bool _lastCharged; [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] private static void UpdateCrosshair_Postfix(Hud __instance, Player player, float bowDrawPercentage) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) Image crosshair = __instance.m_crosshair; if ((Object)(object)crosshair == (Object)null) { return; } if (!Plugin.Enabled.Value || !((Object)(object)player != (Object)null) || (Plugin.RangedOnly.Value && !Plugin.HasRangedWeapon(player))) { ((Behaviour)crosshair).enabled = true; if ((Object)(object)_root != (Object)null) { ((Component)_root).gameObject.SetActive(false); } return; } if ((Object)(object)_root == (Object)null) { CreateOverlay(crosshair); } if (Plugin.SpriteDirty) { RebuildSprites(); } ((Behaviour)crosshair).enabled = false; bool activeSelf = ((Component)crosshair).gameObject.activeSelf; ((Component)_root).gameObject.SetActive(activeSelf); if (!activeSelf) { return; } TargetKind targetKind = (Plugin.TargetColors.Value ? CrosshairTarget.Find(player) : TargetKind.None); switch (targetKind) { case TargetKind.Enemy: ((Graphic)_fill).color = Plugin.EnemyColor.Value; break; case TargetKind.Interactable: ((Graphic)_fill).color = Plugin.InteractColor.Value; break; default: ((Graphic)_fill).color = Plugin.FillColor.Value; break; } bool flag = false; float num = 1f; if (Plugin.ChargeFeedback.Value) { if (bowDrawPercentage > 0f) { float num2 = Mathf.Clamp01(bowDrawPercentage); num = Mathf.Lerp(Plugin.ChargeStartScale.Value, 1f, num2); flag = num2 >= 0.999f; } else { flag = Plugin.IsReloadWeaponLoaded(player); } } ((Graphic)_outline).color = (flag ? Plugin.ChargedColor.Value : Plugin.OutlineColor.Value); ((Transform)_root).localScale = new Vector3(num, num, 1f); if (targetKind != _lastTarget || flag != _lastCharged) { Plugin.Debug($"[HUD] target={targetKind} charged={flag} draw={bowDrawPercentage:0.00}"); _lastTarget = targetKind; _lastCharged = flag; } } private static void CreateOverlay(Image vanilla) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BetterCrosshair", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)vanilla).transform.parent, false); RectTransform rectTransform = ((Graphic)vanilla).rectTransform; _root = (RectTransform)val.transform; _root.anchorMin = rectTransform.anchorMin; _root.anchorMax = rectTransform.anchorMax; _root.pivot = new Vector2(0.5f, 0.5f); _root.anchoredPosition = rectTransform.anchoredPosition; ((Transform)_root).SetSiblingIndex(((Component)vanilla).transform.GetSiblingIndex() + 1); _outline = CreateLayer("Outline", (Transform)(object)_root); _fill = CreateLayer("Fill", (Transform)(object)_root); Plugin.SpriteDirty = true; Plugin.Debug("[HUD] BetterCrosshair overlay created"); } private static Image CreateLayer(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform val2 = (RectTransform)val.transform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.anchoredPosition = Vector2.zero; Image obj = val.AddComponent<Image>(); ((Graphic)obj).raycastTarget = false; obj.preserveAspect = true; return obj; } private static void RebuildSprites() { Plugin.SpriteDirty = false; CrosshairRenderer.Render(Plugin.Shape.Value, Plugin.Size.Value, Plugin.Thickness.Value, Plugin.Gap.Value, Plugin.DotSize.Value, Plugin.OutlineThickness.Value, out var outlineTex, out var fillTex); SetTexture(_outline, ref _outlineTex, outlineTex); SetTexture(_fill, ref _fillTex, fillTex); Plugin.Debug($"[HUD] Sprites rebuilt: {Plugin.Shape.Value}, {((Texture)fillTex).width}x{((Texture)fillTex).height} px"); } private static void SetTexture(Image img, ref Texture2D current, Texture2D tex) { //IL_0047: 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_007e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)img.sprite != (Object)null) { Object.Destroy((Object)(object)img.sprite); } if ((Object)(object)current != (Object)null) { Object.Destroy((Object)(object)current); } current = tex; img.sprite = Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), new Vector2(0.5f, 0.5f), 100f); ((Graphic)img).rectTransform.sizeDelta = new Vector2((float)((Texture)tex).width, (float)((Texture)tex).height); } } internal static class CrosshairTarget { private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[32]; private static int _mask; public static TargetKind Find(Player player) { if (IsEnemyUnderCrosshair(player)) { return TargetKind.Enemy; } GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject != (Object)null && hoverObject.GetComponentInParent<Interactable>() != null) { return TargetKind.Interactable; } return TargetKind.None; } private static bool IsEnemyUnderCrosshair(Player player) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) GameCamera instance = GameCamera.instance; if ((Object)(object)instance == (Object)null) { return false; } if (_mask == 0) { _mask = LayerMask.GetMask(new string[11] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle", "character", "character_net", "character_ghost", "character_noenv", "hitbox" }); } Transform transform = ((Component)instance).transform; int num = Physics.RaycastNonAlloc(transform.position, transform.forward, Hits, Plugin.EnemyRange.Value, _mask, (QueryTriggerInteraction)1); float num2 = float.MaxValue; Collider val = null; for (int i = 0; i < num; i++) { RaycastHit val2 = Hits[i]; if (!(((RaycastHit)(ref val2)).distance >= num2) && !((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Player>() == (Object)(object)player)) { num2 = ((RaycastHit)(ref val2)).distance; val = ((RaycastHit)(ref val2)).collider; } } if ((Object)(object)val == (Object)null) { return false; } Character componentInParent = ((Component)val).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null && !componentInParent.IsDead()) { return BaseAI.IsEnemy((Character)(object)player, componentInParent); } return false; } } internal static class CrosshairRenderer { public static void Render(CrosshairShape shape, int size, int thickness, int gap, int dotSize, int outline, out Texture2D outlineTex, out Texture2D fillTex) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) int num = outline + 1; int num2 = size + num * 2; outlineTex = NewTexture(num2, "BetterCrosshair_Outline"); fillTex = NewTexture(num2, "BetterCrosshair_Fill"); float num3 = (float)num2 / 2f; float half = (float)size / 2f; Color32[] array = (Color32[])(object)new Color32[num2 * num2]; Color32[] array2 = (Color32[])(object)new Color32[num2 * num2]; for (int i = 0; i < num2; i++) { for (int j = 0; j < num2; j++) { float px = (float)j + 0.5f - num3; float py = (float)i + 0.5f - num3; float num4 = Distance(shape, px, py, half, thickness, gap, dotSize); float num5 = Mathf.Clamp01(0.5f - num4); float num6 = ((outline > 0) ? Mathf.Clamp01(0.5f - (num4 - (float)outline)) : 0f); int num7 = i * num2 + j; array2[num7] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num5 * 255f)); array[num7] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num6 * 255f)); } } fillTex.SetPixels32(array2); fillTex.Apply(false, true); outlineTex.SetPixels32(array); outlineTex.Apply(false, true); } private static Texture2D NewTexture(int size, string name) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_001f: Expected O, but got Unknown return new Texture2D(size, size, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, name = name }; } private static float Distance(CrosshairShape shape, float px, float py, float half, int thickness, int gap, int dotSize) { float num = float.MaxValue; bool num2 = shape == CrosshairShape.Cross || shape == CrosshairShape.CrossAndDot; bool flag = shape == CrosshairShape.Circle || shape == CrosshairShape.CircleAndDot; bool flag2 = shape == CrosshairShape.Dot || shape == CrosshairShape.CrossAndDot || shape == CrosshairShape.CircleAndDot; if (num2) { float num3 = Mathf.Min((float)gap, half - 1f); float num4 = (half - num3) / 2f; float num5 = num3 + num4; float hy = (float)thickness / 2f; float num6 = Mathf.Abs(px); float num7 = Mathf.Abs(py); num = Mathf.Min(num, Box(num6 - num5, num7, num4, hy)); num = Mathf.Min(num, Box(num7 - num5, num6, num4, hy)); } if (flag) { float num8 = half - (float)thickness / 2f; num = Mathf.Min(num, Mathf.Abs(Mathf.Sqrt(px * px + py * py) - num8) - (float)thickness / 2f); } if (flag2) { num = Mathf.Min(num, Mathf.Sqrt(px * px + py * py) - (float)dotSize / 2f); } return num; } private static float Box(float x, float y, float hx, float hy) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Abs(x) - hx; float num2 = Mathf.Abs(y) - hy; Vector2 val = new Vector2(Mathf.Max(num, 0f), Mathf.Max(num2, 0f)); float magnitude = ((Vector2)(ref val)).magnitude; float num3 = Mathf.Min(Mathf.Max(num, num2), 0f); return magnitude + num3; } } }