Decompiled source of ProjectileTweaks v1.6.0

ProjectileTweaks.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Configs;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ProjectileTweaks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProjectileTweaks")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.6.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.0.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 ProjectileTweaks
{
	[BepInPlugin("Searica.Valheim.ProjectileTweaks", "ProjectileTweaks", "1.6.0")]
	[BepInDependency("com.jotunn.jotunn", "2.22.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal class ProjectileTweaks : BaseUnityPlugin
	{
		internal class ProjectileConfig
		{
			public string SectionName { get; private set; }

			public string ProjectileType { get; private set; }

			public float DefaultSpread { get; private set; }

			public float DefaultVelocity { get; private set; }

			public float DefaultLaunchAngle { get; private set; }

			public float DefaultLoadSpeed { get; private set; }

			public float DefaultVerticalOffset { get; private set; }

			public float DefaultHorizontalOffset { get; private set; }

			public ConfigEntry<float> SpreadMult { get; private set; }

			public ConfigEntry<float> VelocityMult { get; private set; }

			public ConfigEntry<float> LaunchAngle { get; private set; }

			public ConfigEntry<float> LoadSpeed { get; private set; }

			public ConfigEntry<float> VerticalOffset { get; private set; }

			public ConfigEntry<float> HorizontalOffset { get; private set; }

			public ProjectileConfig(ConfigFile configFile, string sectionName, float defaultSpread = 1f, float defaultVelocity = 1f, float defaultLaunchAngle = -1f, float defaultVanillaLaunchAngle = float.NaN, float defaultLoadSpeed = 1f, float defaultVerticalOffset = float.NaN, float defaultHorizontalOffset = float.NaN)
			{
				SectionName = sectionName;
				if (defaultLoadSpeed != float.NaN)
				{
					LoadSpeed = configFile.BindConfigInOrder(sectionName, "Load/Draw Speed Multiplier", defaultLoadSpeed, "Multiplier for speed of loading projectiles or drawing bows. Set to 2 to load/draw twice as fast. Does not affect Vanilla scaling with skill level.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f));
					LoadSpeed.SettingChanged += UpdateSettings;
				}
				if (defaultSpread != float.NaN)
				{
					SpreadMult = configFile.BindConfigInOrder(sectionName, "Spread Multiplier", defaultSpread, "Multiplies the min and max projectile spread, so if you set it to zero your projectiles will have zero spread.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f));
					SpreadMult.SettingChanged += UpdateSettings;
				}
				if (defaultVelocity != float.NaN)
				{
					VelocityMult = configFile.BindConfigInOrder(sectionName, "Velocity Multiplier", defaultVelocity, "Multiplies velocity of projectiles.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f));
					VelocityMult.SettingChanged += UpdateSettings;
				}
				if (defaultLaunchAngle != float.NaN)
				{
					LaunchAngle = configFile.BindConfigInOrder(sectionName, "Launch Angle", defaultLaunchAngle, "Changes the launch angle of projectiles. " + ((defaultVanillaLaunchAngle != float.NaN) ? $"Vanilla default is {defaultVanillaLaunchAngle}. " : string.Empty) + "Negative values angle upwards, and positive values angle downwards.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f));
					LaunchAngle.SettingChanged += UpdateSettings;
				}
				if (defaultHorizontalOffset != float.NaN)
				{
					HorizontalOffset = configFile.BindConfigInOrder(sectionName, "Horizontal Offset", defaultHorizontalOffset, "Offsets the location that projectiles are launched from when firing them. Positive shifts it to your characters right. Negative shifts it to your characters left.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f));
					HorizontalOffset.SettingChanged += UpdateSettings;
				}
				if (defaultVerticalOffset != float.NaN)
				{
					VerticalOffset = configFile.BindConfigInOrder(sectionName, "Vertical Offset", defaultVerticalOffset, "Offsets the location that projectiles are launched from when firing them.Positive shifts it upwards.Negative shifts it downwards.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f));
					VerticalOffset.SettingChanged += UpdateSettings;
				}
			}
		}

		public const string Author = "Searica";

		public const string PluginName = "ProjectileTweaks";

		public const string PluginGUID = "Searica.Valheim.ProjectileTweaks";

		public const string PluginVersion = "1.6.0";

		public static ProjectileTweaks Instance;

		private const string BombSection = "Bomb Tweaks";

		private const string BowSection = "Bow Tweaks";

		private const string XbowSection = "Crossbow Tweaks";

		private const string SpearSection = "Spear Tweaks";

		private const string StaffSection = "Staff Tweaks";

		private const string ZoomSection = "Zoom";

		private static bool ShouldSaveConfig = false;

		internal ProjectileConfig BowTweaks;

		internal ProjectileConfig BombTweaks;

		internal ProjectileConfig XBowTweaks;

		internal ProjectileConfig SpearTweaks;

		internal ProjectileConfig StaffTweaks;

		private const string AmmoCountSection = "Ammo Count";

		internal ConfigEntry<bool> EnableBowZoom { get; private set; }

		internal ConfigEntry<bool> EnableXbowZoom { get; private set; }

		internal ConfigEntry<KeyCode> ZoomKey { get; private set; }

		internal ConfigEntry<KeyCode> CancelDrawKey { get; private set; }

		internal ConfigEntry<float> StayInZoomTime { get; private set; }

		internal ConfigEntry<float> TimeToZoomIn { get; private set; }

		internal ConfigEntry<float> ZoomFactor { get; private set; }

		internal ConfigEntry<bool> AutoBowZoom { get; private set; }

		internal bool IsZoomEnabled
		{
			get
			{
				if (!EnableBowZoom.Value)
				{
					return EnableXbowZoom.Value;
				}
				return true;
			}
		}

		internal ConfigEntry<bool> ShowAmmoIcon { get; private set; }

		internal ConfigEntry<Vector2> AmmoIconPosition { get; private set; }

		internal ConfigEntry<Vector2> AmmoIconSize { get; private set; }

		internal ConfigEntry<int> AmmoTextSize { get; private set; }

		internal ConfigEntry<TextAlignmentOptions> AmmoTextAlignment { get; private set; }

		internal ConfigEntry<Color> AmmoTextColor { get; private set; }

		internal ConfigEntry<Vector2> AmmoTextPosition { get; private set; }

		internal static bool ShouldResetIcon { get; set; } = true;


		public void Awake()
		{
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Config.Init("Searica.Valheim.ProjectileTweaks");
			SetUpConfigEntries();
			((BaseUnityPlugin)this).Config.Save();
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.ProjectileTweaks");
			Game.isModded = true;
			((BaseUnityPlugin)this).Config.SetupWatcher();
			SynchronizationManager.OnConfigurationWindowClosed += delegate
			{
				UpdateConfigFile();
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				UpdateConfigFile();
			};
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetUpConfigEntries()
		{
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
			BowTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Bow Tweaks", 1f, 1f, -1f, 0f, 1f, 0.2f, 0.2f);
			BombTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Bomb Tweaks", 1f, 1f, -1f, 0f, float.NaN, 0.5f, 0f);
			XBowTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Crossbow Tweaks", 1f, 1f, -1f, -1f, 1f, 0f, 0f);
			SpearTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Spear Tweaks", 1f, 1f, -1f, 0f, float.NaN, 0.5f, 0.1f);
			StaffTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Staff Tweaks", 1f, 1f, float.NaN, 0f, float.NaN, 0.3f, 0f);
			EnableBowZoom = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Bow Zoom", defaultValue: true, "Set to true/enabled to allow zooming while using a bow.");
			EnableBowZoom.SettingChanged += UpdateSettings;
			EnableXbowZoom = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Crossbow Zoom", defaultValue: true, "Set to true/enabled to allow zooming while using a crossbow.");
			EnableXbowZoom.SettingChanged += UpdateSettings;
			ZoomKey = ((BaseUnityPlugin)this).Config.BindConfigInOrder<KeyCode>("Zoom", "Zoom Key", (KeyCode)324, "Set the key used to zoom in while using a bow or crossbow.", synced: false);
			ZoomKey.SettingChanged += UpdateSettings;
			CancelDrawKey = ((BaseUnityPlugin)this).Config.BindConfigInOrder<KeyCode>("Zoom", "Cancel Draw Key", (KeyCode)101, "Set the key used to cancel drawing your bow.", synced: false);
			CancelDrawKey.SettingChanged += UpdateSettings;
			TimeToZoomIn = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Time to Zoom in", 1f, "Time that it takes to zoom in all the way. '1' is default and recommended.", synced: false, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 2f));
			TimeToZoomIn.SettingChanged += UpdateSettings;
			StayInZoomTime = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Stay In-Zoom Time", 2f, "Set the maximum time the camera will stay zoomed in while holding the zoom key after firing a projectile.", synced: false, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f));
			StayInZoomTime.SettingChanged += UpdateSettings;
			ZoomFactor = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Zoom Factor", 2f, "Set how much too zoom in relative to current camera view.", synced: false, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f));
			ZoomFactor.SettingChanged += UpdateSettings;
			AutoBowZoom = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Auto Bow Zoom", defaultValue: false, "Set to true/enabled to make bows automatically zoom in as they are drawn.", synced: false);
			AutoBowZoom.SettingChanged += UpdateSettings;
			ShowAmmoIcon = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Ammo Count", "Show Ammo Icon", defaultValue: true, "Whether to show ammo count icon in hot bar.", synced: false);
			AmmoIconPosition = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Vector2>("Ammo Count", "Icon Position", new Vector2(0f, 32f), "Icon Position.", synced: false);
			AmmoIconSize = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Vector2>("Ammo Count", "Icon Size", new Vector2(20f, 20f), "Icon Size", synced: false);
			AmmoTextSize = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Ammo Count", "Text Size", 16, "Text Size", synced: false);
			AmmoTextAlignment = ((BaseUnityPlugin)this).Config.BindConfigInOrder<TextAlignmentOptions>("Ammo Count", "Text Alignment", (TextAlignmentOptions)260, "Text Alignment", synced: false);
			AmmoTextColor = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Color>("Ammo Count", "Text Color", new Color(1f, 1f, 1f, 1f), "Text Color", synced: false);
			AmmoTextPosition = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Vector2>("Ammo Count", "Text Positio", new Vector2(-6f, -4f), "Offset of text relative to icon", synced: false);
			ShowAmmoIcon.SettingChanged += UpdateSettings;
			AmmoIconPosition.SettingChanged += UpdateSettings;
			AmmoIconSize.SettingChanged += UpdateSettings;
			AmmoTextSize.SettingChanged += UpdateSettings;
			AmmoTextAlignment.SettingChanged += UpdateSettings;
			AmmoTextColor.SettingChanged += UpdateSettings;
			AmmoTextPosition.SettingChanged += UpdateSettings;
			ShowAmmoIcon.SettingChanged += SetUpdateIcon;
			AmmoIconPosition.SettingChanged += SetUpdateIcon;
			AmmoIconSize.SettingChanged += SetUpdateIcon;
			AmmoTextSize.SettingChanged += SetUpdateIcon;
			AmmoTextAlignment.SettingChanged += SetUpdateIcon;
			AmmoTextColor.SettingChanged += SetUpdateIcon;
			AmmoTextPosition.SettingChanged += SetUpdateIcon;
		}

		private void UpdateConfigFile()
		{
			if (ShouldSaveConfig)
			{
				((BaseUnityPlugin)this).Config.Save();
				ShouldSaveConfig = false;
			}
		}

		private static void UpdateSettings(object obj, EventArgs e)
		{
			ShouldSaveConfig |= !ShouldSaveConfig;
		}

		private static void SetUpdateIcon(object obj, EventArgs e)
		{
			ShouldResetIcon |= !ShouldResetIcon;
		}
	}
	[HarmonyPatch]
	internal static class ZoomManager
	{
		internal enum ZoomState
		{
			Fixed,
			ZoomingIn,
			ZoomingOut
		}

		private static ZoomState CurrentZoomState;

		private static float ZoomInTimer;

		private static float ZoomOutTimer;

		private static float ZoomOutDelayTimer;

		private static float BaseFov;

		private static float LastZoomFov;

		private static float NewZoomFov;

		private const float DiffTol = 0.1f;

		private const float PercTol = 0.01f;

		private const float ZoomOutDuration = 1f;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		[HarmonyPriority(0)]
		private static void UpdateCameraPrefix(GameCamera __instance)
		{
			if (ProjectileTweaks.Instance.IsZoomEnabled && (CurrentZoomState == ZoomState.ZoomingOut || CurrentZoomState == ZoomState.ZoomingIn))
			{
				__instance.m_fov = NewZoomFov;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		[HarmonyPriority(200)]
		private static void UpdateCameraPostfix(GameCamera __instance)
		{
			if ((Object)(object)__instance != (Object)null && ProjectileTweaks.Instance.IsZoomEnabled && CurrentZoomState == ZoomState.Fixed && Mathf.Abs(__instance.m_fov - BaseFov) > 0.1f)
			{
				BaseFov = __instance.m_fov;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "SetControls")]
		private static void SetControlsPrefix(Player __instance, ref bool attackHold, ref bool blockHold)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (ProjectileTweaks.Instance.IsZoomEnabled)
			{
				if (attackHold)
				{
					blockHold = Input.GetKey(ProjectileTweaks.Instance.CancelDrawKey.Value);
				}
				else if (CurrentZoomState == ZoomState.ZoomingIn && HasZoomableItem(__instance))
				{
					blockHold = false;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
		[HarmonyPriority(0)]
		private static void UpdateCrosshairPostfix(Player player, float bowDrawPercentage)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!ProjectileTweaks.Instance.IsZoomEnabled || BaseFov == 0f)
			{
				return;
			}
			if (!HasZoomableItem(player))
			{
				ZoomOut();
				return;
			}
			bool key = Input.GetKey(ProjectileTweaks.Instance.ZoomKey.Value);
			bool num = (key || ProjectileTweaks.Instance.AutoBowZoom.Value) && bowDrawPercentage > 0.01f;
			bool flag = key && ((Humanoid)player).IsWeaponLoaded();
			if (num || flag)
			{
				ZoomIn();
			}
			else if (key && bowDrawPercentage <= 0.01f)
			{
				ProcessZoomOutDelay();
			}
			else
			{
				ZoomOut();
			}
		}

		internal static void ZoomIn()
		{
			ZoomInTimer += Time.deltaTime;
			CurrentZoomState = ZoomState.ZoomingIn;
			float num = Mathf.InverseLerp(0.05f, ProjectileTweaks.Instance.TimeToZoomIn.Value, ZoomInTimer);
			LastZoomFov = Mathf.Lerp(BaseFov, BaseFov / ProjectileTweaks.Instance.ZoomFactor.Value, num);
			GameCamera.instance.m_fov = LastZoomFov;
			NewZoomFov = LastZoomFov;
		}

		public static void ZoomOut()
		{
			if (CurrentZoomState != 0)
			{
				if (CurrentZoomState == ZoomState.ZoomingIn)
				{
					CurrentZoomState = ZoomState.ZoomingOut;
					ZoomOutTimer = 0f;
					ZoomInTimer = 0f;
				}
				else
				{
					ZoomOutTimer += Time.deltaTime;
					if (ZoomOutTimer > 1f)
					{
						GameCamera.instance.m_fov = BaseFov;
						CurrentZoomState = ZoomState.Fixed;
						ZoomOutDelayTimer = 0f;
						return;
					}
				}
				float num = Mathf.InverseLerp(0f, 0.3f, ZoomOutTimer);
				NewZoomFov = Mathf.Lerp(LastZoomFov, BaseFov, num);
				GameCamera.instance.m_fov = NewZoomFov;
			}
			else if (Mathf.Abs(GameCamera.instance.m_fov - BaseFov) >= 0.1f)
			{
				GameCamera.instance.m_fov = BaseFov;
			}
		}

		internal static void ProcessZoomOutDelay()
		{
			ZoomOutDelayTimer += Time.deltaTime;
			if (ZoomOutDelayTimer > ProjectileTweaks.Instance.StayInZoomTime.Value)
			{
				ZoomOut();
			}
		}

		internal static bool HasZoomableItem(Player player)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			if (currentWeapon != null)
			{
				SkillType skillType = currentWeapon.m_shared.m_skillType;
				bool num = ProjectileTweaks.Instance.EnableBowZoom.Value && (int)skillType == 8;
				bool flag = ProjectileTweaks.Instance.EnableXbowZoom.Value && (int)skillType == 14;
				return num || flag;
			}
			return false;
		}
	}
}
namespace ProjectileTweaks.Patches
{
	[HarmonyPatch]
	internal static class AmmoCountPatches
	{
		private const string FontName = "Valheim-AveriaSansLibre";

		private static bool HasWarnedAboutFont;

		private const FontStyles FontStyle = 1;

		private static TMP_FontAsset _CurrentFont;

		private const string AmmoCountName = "AmmoCount";

		private static TMP_FontAsset CurrentFont
		{
			get
			{
				if (_CurrentFont == null)
				{
					TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
					foreach (TMP_FontAsset val in array)
					{
						if (((Object)val).name == "Valheim-AveriaSansLibre")
						{
							_CurrentFont = val;
							break;
						}
					}
				}
				if (!HasWarnedAboutFont && _CurrentFont == null)
				{
					HasWarnedAboutFont = true;
					Log.LogWarning("Could not find font Valheim-AveriaSansLibre! Falling back to default font.");
				}
				return _CurrentFont;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HotkeyBar), "Update")]
		private static void UpdateHotkeyBarAmmoCounter(HotkeyBar __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			for (int i = 0; i < __instance.m_items.Count(); i++)
			{
				ItemData val = __instance.m_items[i];
				int x = val.m_gridPos.x;
				if (x >= 0 && x < __instance.m_elements.Count() && __instance.m_elements[x] != null)
				{
					ElementData val2 = __instance.m_elements[x];
					GameObject go = val2.m_go;
					Transform ammoCount = go.transform.Find("AmmoCount");
					if (Object.op_Implicit((Object)(object)ammoCount) && (ProjectileTweaks.ShouldResetIcon || val2.m_used))
					{
						Object.DestroyImmediate((Object)(object)((Component)ammoCount).gameObject);
						AddAmmoCounter(go, out ammoCount);
					}
					else if (!Object.op_Implicit((Object)(object)ammoCount))
					{
						AddAmmoCounter(go, out ammoCount);
					}
					CheckAmmoCount(val, ((Component)ammoCount).gameObject);
				}
			}
			ProjectileTweaks.ShouldResetIcon = false;
		}

		private static void AddAmmoCounter(GameObject gameObject, out Transform ammoCount)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("AmmoCount");
			val.transform.SetParent(gameObject.transform);
			val.AddComponent<RectTransform>().anchoredPosition = Vector2.zero;
			ammoCount = val.transform;
			GameObject val2 = new GameObject("Text");
			val2.transform.SetParent(val.transform);
			TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)val3).rectTransform;
			rectTransform.anchoredPosition = ProjectileTweaks.Instance.AmmoTextPosition.Value;
			rectTransform.sizeDelta = new Vector2(90f, 90f);
			if ((Object)(object)CurrentFont != (Object)null)
			{
				((TMP_Text)val3).font = CurrentFont;
			}
			((TMP_Text)val3).fontSize = ProjectileTweaks.Instance.AmmoTextSize.Value;
			((TMP_Text)val3).fontStyle = (FontStyles)1;
			((TMP_Text)val3).alignment = ProjectileTweaks.Instance.AmmoTextAlignment.Value;
			((Graphic)val3).color = ProjectileTweaks.Instance.AmmoTextColor.Value;
			if (ProjectileTweaks.Instance.ShowAmmoIcon.Value)
			{
				GameObject val4 = new GameObject("Icon");
				val4.transform.SetParent(val.transform);
				val4.AddComponent<Image>();
				RectTransform component = val4.GetComponent<RectTransform>();
				component.anchoredPosition = ProjectileTweaks.Instance.AmmoIconPosition.Value;
				component.sizeDelta = ProjectileTweaks.Instance.AmmoIconSize.Value;
			}
		}

		private static void CheckAmmoCount(ItemData itemData, GameObject go)
		{
			if (!TryGetAmmo(itemData, out var ammoItemData))
			{
				go.SetActive(false);
				return;
			}
			go.SetActive(true);
			((TMP_Text)((Component)go.transform.Find("Text")).GetComponent<TextMeshProUGUI>()).text = ammoItemData.m_stack.ToString();
			if (ProjectileTweaks.Instance.ShowAmmoIcon.Value)
			{
				((Component)go.transform.Find("Icon")).GetComponent<Image>().sprite = ammoItemData.GetIcon();
			}
		}

		private static bool TryGetAmmo(ItemData weapon, out ItemData ammoItemData)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			ammoItemData = null;
			if (string.IsNullOrEmpty(weapon.m_shared.m_ammoType) || (int)weapon.m_shared.m_itemType == 9)
			{
				return false;
			}
			ammoItemData = ((Humanoid)Player.m_localPlayer).GetAmmoItem();
			if (ammoItemData != null && (!((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(ammoItemData) || ammoItemData.m_shared.m_ammoType != weapon.m_shared.m_ammoType))
			{
				ammoItemData = null;
			}
			if (ammoItemData == null)
			{
				ammoItemData = ((Humanoid)Player.m_localPlayer).GetInventory().GetAmmoItem(weapon.m_shared.m_ammoType, (string)null);
			}
			return ammoItemData != null;
		}
	}
	[HarmonyPatch(typeof(Attack))]
	internal static class AttackPatch
	{
		private static float m_projectileVel;

		private static float m_projectileVelMin;

		private static float m_projectileAccuracy;

		private static float m_projectileAccuracyMin;

		[HarmonyPostfix]
		[HarmonyBefore(new string[] { "blacks7ar.BowPlugin" })]
		[HarmonyPriority(700)]
		[HarmonyPatch("Start")]
		internal static void AttackStartPrefix(Attack __instance)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0019: Invalid comparison between Unknown and I4
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Invalid comparison between Unknown and I4
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Invalid comparison between Unknown and I4
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Invalid comparison between Unknown and I4
			ItemData playerWeapon = GetPlayerWeapon(__instance);
			if (playerWeapon != null)
			{
				SkillType skillType = playerWeapon.m_shared.m_skillType;
				if ((int)skillType == 8)
				{
					SetVelocity(__instance, ProjectileTweaks.Instance.BowTweaks.VelocityMult);
					SetSpread(__instance, ProjectileTweaks.Instance.BowTweaks.SpreadMult);
					SetLaunchAngle(__instance, ProjectileTweaks.Instance.BowTweaks.LaunchAngle);
				}
				else if ((int)skillType == 14)
				{
					SetVelocity(__instance, ProjectileTweaks.Instance.XBowTweaks.VelocityMult);
					SetSpread(__instance, ProjectileTweaks.Instance.XBowTweaks.SpreadMult);
					SetLaunchAngle(__instance, ProjectileTweaks.Instance.XBowTweaks.LaunchAngle);
				}
				else if ((int)skillType == 5)
				{
					SetVelocity(__instance, ProjectileTweaks.Instance.SpearTweaks.VelocityMult);
					SetSpread(__instance, ProjectileTweaks.Instance.SpearTweaks.SpreadMult);
					SetLaunchAngle(__instance, ProjectileTweaks.Instance.SpearTweaks.LaunchAngle);
				}
				else if ((int)skillType == 9)
				{
					SetVelocity(__instance, ProjectileTweaks.Instance.StaffTweaks.VelocityMult);
					SetSpread(__instance, ProjectileTweaks.Instance.StaffTweaks.SpreadMult);
				}
				else if (IsBomb(playerWeapon))
				{
					SetVelocity(__instance, ProjectileTweaks.Instance.BombTweaks.VelocityMult);
					SetSpread(__instance, ProjectileTweaks.Instance.BombTweaks.SpreadMult);
					SetLaunchAngle(__instance, ProjectileTweaks.Instance.BombTweaks.LaunchAngle);
				}
			}
		}

		private static void SetVelocity(Attack attack, ConfigEntry<float> velocityMultiplier)
		{
			m_projectileVel = attack.m_projectileVel;
			m_projectileVelMin = attack.m_projectileVelMin;
			velocityMultiplier.SettingChanged += delegate
			{
				attack.m_projectileVel = m_projectileVel * velocityMultiplier.Value;
				attack.m_projectileVelMin = m_projectileVelMin * velocityMultiplier.Value;
			};
			Attack obj = attack;
			obj.m_projectileVel *= velocityMultiplier.Value;
			Attack obj2 = attack;
			obj2.m_projectileVelMin *= velocityMultiplier.Value;
		}

		private static void SetSpread(Attack attack, ConfigEntry<float> spreadConfig)
		{
			m_projectileAccuracy = attack.m_projectileAccuracy;
			m_projectileAccuracyMin = attack.m_projectileAccuracyMin;
			spreadConfig.SettingChanged += delegate
			{
				attack.m_projectileAccuracy = m_projectileAccuracy * spreadConfig.Value;
				attack.m_projectileAccuracyMin = m_projectileAccuracyMin * spreadConfig.Value;
			};
			Attack obj = attack;
			obj.m_projectileAccuracy *= spreadConfig.Value;
			Attack obj2 = attack;
			obj2.m_projectileAccuracyMin *= spreadConfig.Value;
		}

		private static void SetLaunchAngle(Attack attack, ConfigEntry<float> angleConfig)
		{
			angleConfig.SettingChanged += delegate
			{
				attack.m_launchAngle = angleConfig.Value;
			};
			attack.m_launchAngle = angleConfig.Value;
		}

		[HarmonyPostfix]
		[HarmonyPatch("GetProjectileSpawnPoint")]
		private static void GetProjectileSpawnPointPostfix(Attack __instance, ref Vector3 spawnPoint, ref Vector3 aimDir)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0019: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Invalid comparison between Unknown and I4
			ItemData playerWeapon = GetPlayerWeapon(__instance);
			if (playerWeapon != null)
			{
				SkillType skillType = playerWeapon.m_shared.m_skillType;
				if ((int)skillType == 8)
				{
					ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.BowTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.BowTweaks.HorizontalOffset.Value);
				}
				else if ((int)skillType == 14)
				{
					ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.XBowTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.XBowTweaks.HorizontalOffset.Value);
				}
				else if ((int)skillType == 5)
				{
					ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.SpearTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.SpearTweaks.HorizontalOffset.Value);
				}
				else if ((int)skillType == 9)
				{
					ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.StaffTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.StaffTweaks.HorizontalOffset.Value);
				}
				else if (IsBomb(playerWeapon))
				{
					ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.BombTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.BombTweaks.HorizontalOffset.Value);
				}
			}
		}

		private static void ApplyOffset(ref Vector3 spawnPoint, ref Vector3 aimDir, float vertOffset, float horzOffset)
		{
			//IL_0012: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_004c: 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)
			Vector3 val = new Vector3(aimDir.z, 0f, 0f - aimDir.x);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			normalized *= horzOffset;
			spawnPoint += normalized;
			spawnPoint += new Vector3(0f, vertOffset, 0f);
		}

		private static ItemData GetPlayerWeapon(Attack attack)
		{
			if (attack != null)
			{
				Humanoid character = attack.m_character;
				Player val = (Player)(object)((character is Player) ? character : null);
				if (val != null && (((Character)val).m_name == "Human" || (Object)(object)val == (Object)(object)Player.m_localPlayer))
				{
					return ((Humanoid)val).GetCurrentWeapon();
				}
			}
			return null;
		}

		private static bool IsBomb(ItemData item)
		{
			return item.m_shared.m_attack.m_attackAnimation == "throw_bomb";
		}
	}
	[HarmonyPatch(typeof(Humanoid))]
	internal static class HumanoidPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		[HarmonyPatch("GetAttackDrawPercentage")]
		private static void GetAttackDrawPercentagePrefix(Humanoid __instance, out float __state)
		{
			if (Object.op_Implicit((Object)(object)__instance) && (Object)(object)((__instance is Player) ? __instance : null) == (Object)(object)Player.m_localPlayer)
			{
				ItemData currentWeapon = __instance.GetCurrentWeapon();
				if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_bowDraw)
				{
					__state = currentWeapon.m_shared.m_attack.m_drawDurationMin;
					currentWeapon.m_shared.m_attack.m_drawDurationMin = __state * (1f / ProjectileTweaks.Instance.BowTweaks.LoadSpeed.Value);
					return;
				}
			}
			__state = -1f;
		}

		[HarmonyPostfix]
		[HarmonyPriority(800)]
		[HarmonyPatch("GetAttackDrawPercentage")]
		private static void GetAttackDrawPercentagePostfix(Humanoid __instance, ref float __state)
		{
			if (__state != -1f)
			{
				ItemData currentWeapon = __instance.GetCurrentWeapon();
				if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_bowDraw)
				{
					currentWeapon.m_shared.m_attack.m_drawDurationMin = __state;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemData))]
	internal static class ItemDataPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		[HarmonyPatch("GetWeaponLoadingTime")]
		public static void GetWeaponLoadingTimePrefix(ItemData __instance, out float __state)
		{
			if (__instance.m_shared.m_attack.m_requiresReload)
			{
				__state = __instance.m_shared.m_attack.m_reloadTime;
				Attack attack = __instance.m_shared.m_attack;
				attack.m_reloadTime *= 1f / ProjectileTweaks.Instance.XBowTweaks.LoadSpeed.Value;
			}
			else
			{
				__state = -1f;
			}
		}

		[HarmonyPostfix]
		[HarmonyPriority(800)]
		[HarmonyPatch("GetWeaponLoadingTime")]
		public static void GetWeaponLoadingTimePostfix(ItemData __instance, ref float __state)
		{
			if (__instance.m_shared.m_attack.m_requiresReload && __state != -1f)
			{
				__instance.m_shared.m_attack.m_reloadTime = __state;
			}
		}
	}
}
namespace Logging
{
	internal static class Log
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource logSource;

		internal static ConfigEntry<InfoLevel> Verbosity { get; set; }

		internal static InfoLevel VerbosityLevel => Verbosity.Value;

		internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;

		internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;

		internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			logSource.LogFatal(data);
		}

		internal static void LogMessage(object data)
		{
			logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			logSource.LogWarning(data);
		}

		internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				logSource.LogInfo(data);
			}
		}

		internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			LogInfo("***** " + ((Object)prefab).name + " *****");
			Component[] components = prefab.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				LogComponent(components[i]);
			}
			if (!includeChildren)
			{
				return;
			}
			LogInfo("***** " + ((Object)prefab).name + " (children) *****");
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (Object.op_Implicit((Object)(object)val))
				{
					LogInfo(" - " + ((Object)val).name);
					components = ((Component)val).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						LogComponent(components[i]);
					}
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			if (!Object.op_Implicit((Object)(object)compo))
			{
				return;
			}
			try
			{
				LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			}
			catch (Exception ex)
			{
				LogError(ex.ToString());
				LogWarning("Could not get type name for component!");
				return;
			}
			try
			{
				foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
					}
					catch (Exception ex2)
					{
						LogError(ex2.ToString());
						LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
					}
				}
			}
			catch (Exception ex3)
			{
				LogError(ex3.ToString());
				LogWarning("Could not get properties for component!");
			}
			try
			{
				foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
					}
					catch (Exception ex4)
					{
						LogError(ex4.ToString());
						LogWarning("Could not get field: " + declaredField.Name + " for component!");
					}
				}
			}
			catch (Exception ex5)
			{
				LogError(ex5.ToString());
				LogWarning("Could not get fields for component!");
			}
		}
	}
}
namespace Configs
{
	public static class ConfigFileManager
	{
		internal class ConfigFileOrderingMaps
		{
			public Dictionary<string, int> sectionToSectionNumber = new Dictionary<string, int>();

			public Dictionary<string, int> sectionToSettingOrder = new Dictionary<string, int>();
		}

		internal static string ConfigFileName;

		internal static string ConfigFileFullPath;

		internal static DateTime lastRead = DateTime.MinValue;

		private static readonly Dictionary<string, ConfigFileOrderingMaps> _configFileOrderingMaps = new Dictionary<string, ConfigFileOrderingMaps>();

		private static readonly List<string> ConfigManagerGUIDs = new List<string> { "_shudnal.ConfigurationManager", "com.bepis.bepinex.configurationmanager" };

		private static BaseUnityPlugin _configManager = null;

		private const string WindowChangedEventName = "DisplayingWindowChanged";

		private const string DisplayingWindowName = "DisplayingWindow";

		private static PropertyInfo _dispWindowInfo = null;

		private static BaseUnityPlugin ConfigManager
		{
			get
			{
				if ((Object)(object)_configManager == (Object)null)
				{
					foreach (string configManagerGUID in ConfigManagerGUIDs)
					{
						if (Chainloader.PluginInfos.TryGetValue(configManagerGUID, out var value) && Object.op_Implicit((Object)(object)value.Instance))
						{
							_configManager = value.Instance;
							break;
						}
					}
				}
				return _configManager;
			}
		}

		private static PropertyInfo DisplayWindowInfo
		{
			get
			{
				if ((object)_dispWindowInfo == null)
				{
					_dispWindowInfo = ((object)ConfigManager).GetType().GetProperty("DisplayingWindow");
				}
				return _dispWindowInfo;
			}
		}

		internal static event Action OnConfigFileReloaded;

		internal static event Action OnConfigWindowClosed;

		private static string GetOrderedSectionName(this ConfigFile configFile, string section)
		{
			if (!_configFileOrderingMaps.TryGetValue(configFile.ConfigFilePath, out var value))
			{
				value = new ConfigFileOrderingMaps();
				_configFileOrderingMaps.Add(configFile.ConfigFilePath, value);
			}
			if (!value.sectionToSectionNumber.TryGetValue(section, out var value2))
			{
				value2 = value.sectionToSectionNumber.Count + 1;
				value.sectionToSectionNumber[section] = value2;
			}
			return $"{value2} - {section}";
		}

		private static int GetSettingOrder(this ConfigFile configFile, string section)
		{
			if (!_configFileOrderingMaps.TryGetValue(configFile.ConfigFilePath, out var value))
			{
				value = new ConfigFileOrderingMaps();
				_configFileOrderingMaps.Add(configFile.ConfigFilePath, value);
			}
			if (!value.sectionToSettingOrder.TryGetValue(section, out var value2))
			{
				value2 = 0;
			}
			value.sectionToSettingOrder[section] = value2 - 1;
			return value2;
		}

		internal static string GetExtendedDescription(string description, bool synchronizedSetting)
		{
			return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]");
		}

		private static void InvokeOnConfigFileReloaded()
		{
			Action onConfigFileReloaded = ConfigFileManager.OnConfigFileReloaded;
			if (onConfigFileReloaded != null)
			{
				onConfigFileReloaded.SafeInvoke();
			}
		}

		private static void InvokeOnConfigWindowClosed()
		{
			Action onConfigWindowClosed = ConfigFileManager.OnConfigWindowClosed;
			if (onConfigWindowClosed != null)
			{
				onConfigWindowClosed.SafeInvoke();
			}
		}

		public static void Init(this ConfigFile configFile, string GUID, bool saveOnConfigSet = false)
		{
			configFile.SaveOnConfigSet = saveOnConfigSet;
			ConfigFileName = GUID + ".cfg";
			ConfigFileFullPath = Path.Combine(Paths.ConfigPath, ConfigFileName);
		}

		public static bool DisableSaveOnConfigSet(this ConfigFile configFile)
		{
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			configFile.SaveOnConfigSet = false;
			return saveOnConfigSet;
		}

		public static ConfigEntry<T> BindConfigInOrder<T>(this ConfigFile configFile, string section, string key, T defaultValue, string description, bool synced = true, bool sectionOrder = true, bool settingOrder = true, AcceptableValueBase acceptableValues = null, Action<ConfigEntryBase> customDrawer = null, ConfigurationManagerAttributes configAttributes = null)
		{
			section = (sectionOrder ? configFile.GetOrderedSectionName(section) : section);
			int value = (settingOrder ? configFile.GetSettingOrder(section) : 0);
			return configFile.BindConfig(section, key, defaultValue, description, synced, value, acceptableValues, customDrawer, configAttributes);
		}

		public static ConfigEntry<T> BindConfig<T>(this ConfigFile configFile, string section, string key, T defaultValue, string description, bool synced = true, int? order = null, AcceptableValueBase acceptableValues = null, Action<ConfigEntryBase> customDrawer = null, ConfigurationManagerAttributes configAttributes = null)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			string extendedDescription = GetExtendedDescription(description, synced);
			if (configAttributes == null)
			{
				configAttributes = new ConfigurationManagerAttributes();
			}
			configAttributes.IsAdminOnly = synced;
			configAttributes.Order = order;
			configAttributes.CustomDrawer = customDrawer;
			return configFile.Bind<T>(section, key, defaultValue, new ConfigDescription(extendedDescription, acceptableValues, new object[1] { configAttributes }));
		}

		internal static void SetupWatcher(this ConfigFile configFile)
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += configFile.ReloadConfigFile;
			fileSystemWatcher.Created += configFile.ReloadConfigFile;
			fileSystemWatcher.Renamed += configFile.ReloadConfigFile;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		internal static void ReloadConfigFile(this ConfigFile configFile, object sender, FileSystemEventArgs eventArgs)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				DateTime lastWriteTime = File.GetLastWriteTime(eventArgs.FullPath);
				if (lastRead != lastWriteTime)
				{
					Log.LogInfo("Reloading config file");
					bool saveOnConfigSet = configFile.DisableSaveOnConfigSet();
					configFile.Reload();
					configFile.SaveOnConfigSet = saveOnConfigSet;
					InvokeOnConfigFileReloaded();
					lastRead = lastWriteTime;
				}
			}
			catch
			{
				Log.LogError("There was an issue loading your " + ConfigFileName);
				Log.LogError("Please check your config entries for spelling and format!");
			}
		}

		internal static void CheckForConfigManager(this ConfigFile config)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)SystemInfo.graphicsDeviceType != 4 && !((Object)(object)ConfigManager == (Object)null))
			{
				Log.LogDebug("Configuration manager found, hooking DisplayingWindowChanged");
				EventInfo @event = ((object)ConfigManager).GetType().GetEvent("DisplayingWindowChanged");
				if (!(@event == null))
				{
					Action<object, object> action = OnConfigManagerDisplayingWindowChanged;
					Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method);
					@event.AddEventHandler(ConfigManager, handler);
				}
			}
		}

		private static void OnConfigManagerDisplayingWindowChanged(object sender, object e)
		{
			if (!(DisplayWindowInfo == null) && !(bool)DisplayWindowInfo.GetValue(ConfigManager, null))
			{
				InvokeOnConfigWindowClosed();
			}
		}

		private static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception arg)
				{
					Log.LogWarning("Exception thrown at event " + new StackFrame(1).GetMethod().Name + $" in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{arg}");
				}
			}
		}
	}
}