Decompiled source of DynamicReticle v0.5.6

DynamicReticle.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DynamicReticle")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DynamicReticle")]
[assembly: AssemblyTitle("DynamicReticle")]
[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 DynamicReticle
{
	[BepInPlugin("kajetan.valheim.dynamicreticle", "Wire's Dynamic Reticles", "0.5.6")]
	public sealed class DynamicReticlePlugin : BaseUnityPlugin
	{
		private enum AttackGroup
		{
			None,
			Spear,
			Magic,
			Other
		}

		public enum EasingMode
		{
			Linear,
			SineInOut,
			ExpoInOut
		}

		[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
		private static class HudUpdateCrosshairPatch
		{
			private static void Postfix(Hud __instance, Player player, float bowDrawPercentage)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.UpdateHud(__instance, player, bowDrawPercentage);
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateStealth")]
		private static class HudUpdateStealthPatch
		{
			private static void Postfix(Hud __instance)
			{
				DisableStealthHud(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "Start")]
		private static class AttackStartPatch
		{
			private static void Postfix(Attack __instance, Humanoid character, ItemData weapon, ref bool __result)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.OnAttackStarted(__instance, character, weapon, __result);
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
		private static class AttackTriggerPatch
		{
			private static void Postfix(Attack __instance)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.OnAttackTriggered(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Attack), "Stop")]
		private static class AttackStopPatch
		{
			private static void Postfix(Attack __instance)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.OnAttackStopped(__instance);
				}
			}
		}

		public const string PluginGuid = "kajetan.valheim.dynamicreticle";

		public const string PluginName = "Wire's Dynamic Reticles";

		public const string PluginVersion = "0.5.6";

		private const float VanillaStartScale = 1f;

		private const float VanillaEndScale = 0.15f;

		private const float VanillaCrosshairIdleAlpha = 0.5f;

		internal static DynamicReticlePlugin Instance;

		private Harmony _harmony;

		private Image _customRing;

		private Hud _customRingHud;

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<bool> _disableStealth;

		private ConfigEntry<bool> _showHeldCrosshair;

		private ConfigEntry<bool> _showHoverCrosshair;

		private ConfigEntry<float> _crosshairFade;

		private ConfigEntry<bool> _reticleEnabled;

		private ConfigEntry<EasingMode> _easing;

		private float _crosshairVisibility;

		private bool _bowReleaseWaitingForZero;

		private Attack _activeAttack;

		private ItemData _activeWeapon;

		private AttackGroup _activeGroup;

		private bool _activeReleased;

		private readonly Dictionary<string, float> _learnedReleaseTimes = new Dictionary<string, float>(StringComparer.Ordinal);

		private static readonly FieldInfo ActionQueueField = AccessTools.Field(typeof(Player), "m_actionQueue");

		private static readonly FieldInfo AttackCharacterField = AccessTools.Field(typeof(Attack), "m_character");

		private static readonly FieldInfo AttackTimeField = AccessTools.Field(typeof(Attack), "m_time");

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Instance = this;
			BindConfig();
			_harmony = new Harmony("kajetan.valheim.dynamicreticle");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Wire's Dynamic Reticles 0.5.6 loaded.");
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
			Instance = null;
		}

		private void BindConfig()
		{
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch.");
			_disableStealth = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableStealthIndicator", true, "Hide Valheim's crouch/stealth HUD indicator.");
			_showHeldCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "ShowForWeaponsAndTools", true, "Show the normal crosshair while holding any weapon or tool.");
			_showHoverCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "ShowOnHover", true, "Show the normal crosshair when the aimed object has Valheim hover text/name or is interactable.");
			_crosshairFade = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "FadeSeconds", 0.1f, "Normal-crosshair fade duration in and out.");
			_reticleEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Reticle", "Enabled", true, "Enable the animated yellow projectile reticle.");
			_easing = ((BaseUnityPlugin)this).Config.Bind<EasingMode>("Reticle", "Easing", EasingMode.SineInOut, "Reticle scale/color easing. SineInOut is the default; ExpoInOut is punchier.");
		}

		internal void UpdateHud(Hud hud, Player player, float bowDrawPercentage)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Invalid comparison between Unknown and I4
			if ((Object)(object)hud == (Object)null || (Object)(object)player == (Object)null)
			{
				return;
			}
			if (!_enabled.Value)
			{
				if ((Object)(object)_customRing != (Object)null)
				{
					((Component)_customRing).gameObject.SetActive(false);
				}
				return;
			}
			EnsureCustomRing(hud);
			if ((Object)(object)hud.m_crosshairBow != (Object)null)
			{
				((Component)hud.m_crosshairBow).gameObject.SetActive(false);
			}
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			ItemData rightItem = ((Humanoid)player).RightItem;
			UpdateNormalCrosshair(hud, player, rightItem ?? currentWeapon, currentWeapon);
			if (_reticleEnabled.Value && bowDrawPercentage > 0f)
			{
				if (_bowReleaseWaitingForZero)
				{
					HideRing(hud);
				}
				else
				{
					RenderProgress(hud, bowDrawPercentage, useConfiguredEasing: true);
				}
				return;
			}
			if (bowDrawPercentage <= 0f && _bowReleaseWaitingForZero)
			{
				_bowReleaseWaitingForZero = false;
			}
			if (!_reticleEnabled.Value)
			{
				HideRing(hud);
			}
			else if (currentWeapon == null || currentWeapon.m_shared == null)
			{
				HideRing(hud);
			}
			else if ((int)currentWeapon.m_shared.m_skillType == 14)
			{
				RenderCrossbow(hud, player, currentWeapon);
			}
			else if (IsDundr(currentWeapon))
			{
				RenderDundr(hud, player, currentWeapon);
			}
			else if (_activeAttack != null && _activeWeapon == currentWeapon)
			{
				RenderActiveAttack(hud);
			}
			else
			{
				HideRing(hud);
			}
		}

		private void UpdateNormalCrosshair(Hud hud, Player player, ItemData heldItem, ItemData currentWeapon)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			bool flag2 = false;
			GameObject hoverObject = ((Humanoid)player).GetHoverObject();
			if ((Object)(object)hoverObject != (Object)null)
			{
				try
				{
					if (_showHoverCrosshair.Value)
					{
						flag = hoverObject.GetComponentInParent<Interactable>() != null;
						Hoverable componentInParent = hoverObject.GetComponentInParent<Hoverable>();
						if (componentInParent != null)
						{
							string hoverText = componentInParent.GetHoverText();
							string hoverName = componentInParent.GetHoverName();
							flag2 = !string.IsNullOrEmpty(hoverText) || !string.IsNullOrEmpty(hoverName);
						}
					}
				}
				catch
				{
					flag = false;
					flag2 = false;
				}
			}
			bool flag3 = flag || flag2 || (_showHeldCrosshair.Value && IsHeldWeaponOrTool(heldItem, currentWeapon));
			float num = Mathf.Max(0.001f, _crosshairFade.Value);
			_crosshairVisibility = Mathf.MoveTowards(_crosshairVisibility, flag3 ? 1f : 0f, Time.unscaledDeltaTime / num);
			Image crosshair = hud.m_crosshair;
			if (!((Object)(object)crosshair == (Object)null))
			{
				Color color = ((Graphic)crosshair).color;
				float num2 = Mathf.Max(color.a, 0.5f);
				color.a = num2 * _crosshairVisibility;
				((Graphic)crosshair).color = color;
			}
		}

		private static bool IsHeldWeaponOrTool(ItemData heldItem, ItemData currentWeapon)
		{
			//IL_0020: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			if (currentWeapon != null && currentWeapon.m_shared != null)
			{
				return true;
			}
			if (heldItem == null || heldItem.m_shared == null)
			{
				return false;
			}
			ItemType itemType = heldItem.m_shared.m_itemType;
			if ((int)itemType != 19)
			{
				return (int)itemType == 15;
			}
			return true;
		}

		private void RenderCrossbow(Hud hud, Player player, ItemData weapon)
		{
			if (TryGetReloadProgress(player, weapon, out var progress))
			{
				RenderProgress(hud, progress);
			}
			else if (((Humanoid)player).IsWeaponLoaded())
			{
				RenderProgress(hud, 1f);
			}
			else
			{
				HideRing(hud);
			}
		}

		private void RenderDundr(Hud hud, Player player, ItemData weapon)
		{
			if (TryGetReloadProgress(player, weapon, out var progress))
			{
				RenderProgress(hud, progress);
			}
			else if (((Humanoid)player).IsWeaponLoaded())
			{
				RenderProgress(hud, 1f);
			}
			else if (_activeAttack != null && _activeWeapon == weapon && !_activeReleased)
			{
				RenderActiveAttack(hud);
			}
			else
			{
				HideRing(hud);
			}
		}

		private bool TryGetReloadProgress(Player player, ItemData weapon, out float progress)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			progress = 0f;
			if (ActionQueueField == null)
			{
				return false;
			}
			if (!(ActionQueueField.GetValue(player) is IEnumerable enumerable))
			{
				return false;
			}
			foreach (object item in enumerable)
			{
				MinorActionData val = (MinorActionData)((item is MinorActionData) ? item : null);
				if (val != null && (int)val.m_type == 2 && (val.m_item == null || val.m_item == weapon))
				{
					progress = ((val.m_duration <= 0f) ? 1f : Mathf.Clamp01(val.m_time / val.m_duration));
					return true;
				}
			}
			return false;
		}

		private void RenderActiveAttack(Hud hud)
		{
			if (_activeAttack == null)
			{
				HideRing(hud);
			}
			else if (_activeReleased)
			{
				if (IsSustainedBurstAttack(_activeAttack))
				{
					RenderProgress(hud, 1f);
				}
				else
				{
					HideRing(hud);
				}
			}
			else
			{
				float attackElapsed = GetAttackElapsed(_activeAttack);
				float expectedReleaseSeconds = GetExpectedReleaseSeconds(_activeAttack, _activeWeapon, _activeGroup);
				float rawProgress = ((expectedReleaseSeconds <= 0.001f) ? 0f : Mathf.Clamp01(attackElapsed / expectedReleaseSeconds));
				RenderProgress(hud, rawProgress);
			}
		}

		private void RenderProgress(Hud hud, float rawProgress)
		{
			RenderProgress(hud, rawProgress, useConfiguredEasing: true);
		}

		private void RenderProgress(Hud hud, float rawProgress, bool useConfiguredEasing)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			EnsureCustomRing(hud);
			if (!((Object)(object)_customRing == (Object)null))
			{
				rawProgress = Mathf.Clamp01(rawProgress);
				if (rawProgress <= 0f)
				{
					((Component)_customRing).gameObject.SetActive(false);
					return;
				}
				float num = (useConfiguredEasing ? Ease(rawProgress) : rawProgress);
				float num2 = Mathf.Lerp(GetStartScale(), GetEndScale(), num);
				((Component)_customRing).gameObject.SetActive(true);
				((Component)_customRing).transform.localScale = new Vector3(num2, num2, num2);
				((Graphic)_customRing).color = Color.Lerp(new Color(1f, 1f, 1f, 0f), Color.yellow, num);
			}
		}

		internal void OnAttackStarted(Attack attack, Humanoid character, ItemData weapon, bool started)
		{
			if (started && _enabled.Value && attack != null && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && weapon != null && weapon.m_shared != null)
			{
				AttackGroup attackGroup = ClassifyAttack(weapon, attack);
				if (attackGroup != AttackGroup.None)
				{
					_activeAttack = attack;
					_activeWeapon = weapon;
					_activeGroup = attackGroup;
					_activeReleased = false;
				}
			}
		}

		internal void OnAttackTriggered(Attack attack)
		{
			//IL_003f: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Invalid comparison between Unknown and I4
			if (!_enabled.Value || attack == null)
			{
				return;
			}
			Humanoid attackCharacter = GetAttackCharacter(attack);
			if ((Object)(object)attackCharacter != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			ItemData currentWeapon = attackCharacter.GetCurrentWeapon();
			if (currentWeapon == null || currentWeapon.m_shared == null)
			{
				return;
			}
			SkillType skillType = currentWeapon.m_shared.m_skillType;
			if ((int)skillType == 8)
			{
				HideRing(Hud.instance);
				_bowReleaseWaitingForZero = true;
			}
			else if ((int)skillType == 14)
			{
				HideRing(Hud.instance);
			}
			else if (attack == _activeAttack)
			{
				float attackElapsed = GetAttackElapsed(attack);
				if (attackElapsed > 0.03f && attackElapsed < 10f)
				{
					_learnedReleaseTimes[GetAttackKey(attack, _activeWeapon)] = attackElapsed;
				}
				_activeReleased = true;
				if (!IsSustainedBurstAttack(attack))
				{
					HideRing(Hud.instance);
				}
			}
		}

		internal void OnAttackStopped(Attack attack)
		{
			if (attack != null && attack == _activeAttack)
			{
				if (_activeReleased && IsSustainedBurstAttack(attack))
				{
					HideRing(Hud.instance);
				}
				_activeAttack = null;
				_activeWeapon = null;
				_activeGroup = AttackGroup.None;
				_activeReleased = false;
			}
		}

		private AttackGroup ClassifyAttack(ItemData weapon, Attack attack)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (weapon == null || weapon.m_shared == null || !IsProjectileAttack(attack))
			{
				return AttackGroup.None;
			}
			SkillType skillType = weapon.m_shared.m_skillType;
			if ((int)skillType == 8 || (int)skillType == 14)
			{
				return AttackGroup.None;
			}
			if ((int)skillType == 5)
			{
				return AttackGroup.Spear;
			}
			if (IsMagicSkill(skillType))
			{
				if (IsUtilityMagicStaff(weapon))
				{
					return AttackGroup.None;
				}
				return AttackGroup.Magic;
			}
			return AttackGroup.Other;
		}

		private bool IsRangedWeaponForCrosshair(ItemData weapon)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_001b: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (weapon == null || weapon.m_shared == null)
			{
				return false;
			}
			SkillType skillType = weapon.m_shared.m_skillType;
			if ((int)skillType == 8 || (int)skillType == 14 || (int)skillType == 5)
			{
				return true;
			}
			if (IsMagicSkill(skillType) && IsUtilityMagicStaff(weapon))
			{
				return false;
			}
			if (!IsProjectileAttack(weapon.m_shared.m_attack))
			{
				return IsProjectileAttack(weapon.m_shared.m_secondaryAttack);
			}
			return true;
		}

		private float GetExpectedReleaseSeconds(Attack attack, ItemData weapon, AttackGroup group)
		{
			string attackKey = GetAttackKey(attack, weapon);
			if (_learnedReleaseTimes.TryGetValue(attackKey, out var value) && value > 0.03f)
			{
				return value;
			}
			return group switch
			{
				AttackGroup.Spear => 0.55f, 
				AttackGroup.Magic => 0.42f, 
				_ => 0.4f, 
			};
		}

		private float GetScaleForRawProgress(float rawProgress)
		{
			float num = Ease(Mathf.Clamp01(rawProgress));
			return Mathf.Lerp(GetStartScale(), GetEndScale(), num);
		}

		private float GetStartScale()
		{
			return 1f;
		}

		private float GetEndScale()
		{
			return 0.15f;
		}

		private float Ease(float t)
		{
			t = Mathf.Clamp01(t);
			switch (_easing.Value)
			{
			case EasingMode.Linear:
				return t;
			case EasingMode.ExpoInOut:
				if (t <= 0f)
				{
					return 0f;
				}
				if (t >= 1f)
				{
					return 1f;
				}
				if (!(t < 0.5f))
				{
					return (2f - Mathf.Pow(2f, -20f * t + 10f)) / 2f;
				}
				return Mathf.Pow(2f, 20f * t - 10f) / 2f;
			default:
				return (0f - (Mathf.Cos((float)Math.PI * t) - 1f)) / 2f;
			}
		}

		private static bool IsSustainedBurstAttack(Attack attack)
		{
			if (attack != null)
			{
				return attack.m_projectileBursts > 1;
			}
			return false;
		}

		private static string GetAttackKey(Attack attack, ItemData weapon)
		{
			string text = ((weapon != null && weapon.m_shared != null) ? (weapon.m_shared.m_name ?? string.Empty) : string.Empty);
			string text2 = ((attack != null) ? (attack.m_attackAnimation ?? string.Empty) : string.Empty);
			return text + "|" + text2 + "|" + ((attack != null) ? ((object)Unsafe.As<AttackType, AttackType>(ref attack.m_attackType)/*cast due to .constrained prefix*/).ToString() : string.Empty);
		}

		private static float GetAttackElapsed(Attack attack)
		{
			if (attack == null || AttackTimeField == null)
			{
				return 0f;
			}
			object value = AttackTimeField.GetValue(attack);
			if (!(value is float))
			{
				return 0f;
			}
			return (float)value;
		}

		private static Humanoid GetAttackCharacter(Attack attack)
		{
			if (attack == null || AttackCharacterField == null)
			{
				return null;
			}
			object? value = AttackCharacterField.GetValue(attack);
			return (Humanoid)((value is Humanoid) ? value : null);
		}

		private static bool IsProjectileAttack(Attack attack)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			if (attack != null)
			{
				if ((int)attack.m_attackType != 2)
				{
					return (int)attack.m_attackType == 5;
				}
				return true;
			}
			return false;
		}

		private static bool IsMagicSkill(SkillType skill)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)skill != 9)
			{
				return (int)skill == 10;
			}
			return true;
		}

		private static bool IsDundr(ItemData weapon)
		{
			if (weapon != null && weapon.m_shared != null)
			{
				return string.Equals(weapon.m_shared.m_name, "$item_staff_lightning", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private static bool IsUtilityMagicStaff(ItemData weapon)
		{
			if (weapon == null || weapon.m_shared == null)
			{
				return false;
			}
			switch ((weapon.m_shared.m_name ?? string.Empty).ToLowerInvariant())
			{
			case "$item_staffshield":
			case "$item_staffskeleton":
			case "$item_staffredtroll":
			case "$item_staff_frostorbs":
			case "$item_staff_spiritcaller":
				return true;
			default:
				return false;
			}
		}

		internal static void DisableStealthHud(Hud hud)
		{
			if (!((Object)(object)Instance == (Object)null) && Instance._enabled.Value && Instance._disableStealth.Value && !((Object)(object)hud == (Object)null))
			{
				if ((Object)(object)hud.m_targetedAlert != (Object)null)
				{
					hud.m_targetedAlert.SetActive(false);
				}
				if ((Object)(object)hud.m_targeted != (Object)null)
				{
					hud.m_targeted.SetActive(false);
				}
				if ((Object)(object)hud.m_hidden != (Object)null)
				{
					hud.m_hidden.SetActive(false);
				}
				if ((Object)(object)hud.m_stealthBar != (Object)null)
				{
					((Component)hud.m_stealthBar).gameObject.SetActive(false);
				}
			}
		}

		private void EnsureCustomRing(Hud hud)
		{
			if (!((Object)(object)hud == (Object)null) && !((Object)(object)hud.m_crosshairBow == (Object)null) && (!((Object)(object)_customRing != (Object)null) || !((Object)(object)_customRingHud == (Object)(object)hud)))
			{
				if ((Object)(object)_customRing != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_customRing).gameObject);
				}
				_customRingHud = hud;
				_customRing = Object.Instantiate<Image>(hud.m_crosshairBow, ((Component)hud.m_crosshairBow).transform.parent, false);
				((Object)_customRing).name = "DynamicReticleRing";
				((Graphic)_customRing).raycastTarget = false;
				((Component)_customRing).transform.SetSiblingIndex(((Component)hud.m_crosshairBow).transform.GetSiblingIndex() + 1);
				((Component)_customRing).gameObject.SetActive(false);
			}
		}

		private void HideRing(Hud hud)
		{
			if ((Object)(object)_customRing != (Object)null)
			{
				((Component)_customRing).gameObject.SetActive(false);
			}
		}
	}
}