Decompiled source of HeavyIntegration v1.0.0

BepInEx/plugins/HeavyIntegration.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.Movement;
using Pigeon.UI;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Sparroh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("HeavyIntegration")]
[assembly: AssemblyTitle("HeavyIntegration")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[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 HeavyIntegration
{
	public static class ConfigManager
	{
		private const float DebounceSeconds = 0.25f;

		private static ConfigFile config;

		private static ManualLogSource logger;

		private static FileSystemWatcher configWatcher;

		private static volatile bool reloadPending;

		private static float lastReloadTime;

		public static ConfigEntry<bool> LoadoutEnabled { get; private set; }

		public static ConfigEntry<int> HeavyGearId { get; private set; }

		public static ConfigEntry<bool> ReapplyAfterDrop { get; private set; }

		public static ConfigEntry<bool> AmmoRegenEnabled { get; private set; }

		public static ConfigEntry<float> RegenMultiplier { get; private set; }

		public static ConfigEntry<bool> PlayAmmoSound { get; private set; }

		public static ConfigEntry<bool> HeavyFocusEnabled { get; private set; }

		public static ConfigEntry<bool> SelectionUiEnabled { get; private set; }

		public static void Initialize(ConfigFile configFile, ManualLogSource log)
		{
			config = configFile;
			logger = log;
			LoadoutEnabled = config.Bind<bool>("Loadout", "Enabled", true, "When enabled, the selected heavy weapon is kept in your stored (heavy) loadout slot.");
			HeavyGearId = config.Bind<int>("Loadout", "Heavy Gear Id", 0, "GearInfo.ID of the loadout heavy weapon. 0 = none (empty). Prefer selecting in the gear menu.");
			ReapplyAfterDrop = config.Bind<bool>("Loadout", "Reapply After Drop", true, "When true, dropping or clearing a temporary stored pickup restores your loadout heavy.");
			AmmoRegenEnabled = config.Bind<bool>("Ammo Regen", "Enable Feature", true, "When enabled, heavy weapons gain magazine ammo from damage dealt by your other main weapon.");
			RegenMultiplier = config.Bind<float>("Ammo Regen", "Regen Multiplier", 1f, "Multiplier on vanilla damage-to-ammo conversion density for the heavy magazine. 1.0 = same density primaries use; raise if regen feels weak.");
			PlayAmmoSound = config.Bind<bool>("Ammo Regen", "Play Ammo Sound", false, "Play the ammo refund sound when heavy magazine ammo is restored from damage.");
			HeavyFocusEnabled = config.Bind<bool>("Focus", "Enable Heavy Focus", true, "When enabled, unlocked heavies can be Focused in the gear menu (Favorite bind), skewing upgrade drops toward that heavy like primaries.");
			SelectionUiEnabled = config.Bind<bool>("Selection UI", "Enable Feature", true, "When enabled, the heavy crate picker lays out extra slots and scrolls when many heavies are unlocked.");
			try
			{
				SetupFileWatcher();
			}
			catch (Exception ex)
			{
				logger.LogError((object)("Error setting up config file watcher: " + ex.Message));
			}
		}

		public static void SetHeavyGearId(int id)
		{
			if (HeavyGearId != null && HeavyGearId.Value != id)
			{
				HeavyGearId.Value = id;
				config.Save();
			}
		}

		public static void Tick()
		{
			if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f)
			{
				return;
			}
			reloadPending = false;
			lastReloadTime = Time.unscaledTime;
			try
			{
				config.Reload();
				logger.LogInfo((object)"Config reloaded from disk.");
				HeavyLoadoutService.OnConfigReloaded();
			}
			catch (Exception ex)
			{
				logger.LogError((object)("Error reloading config: " + ex.Message));
			}
		}

		public static void Dispose()
		{
			if (configWatcher != null)
			{
				configWatcher.EnableRaisingEvents = false;
				configWatcher.Changed -= OnConfigFileChanged;
				configWatcher.Created -= OnConfigFileChanged;
				configWatcher.Renamed -= OnConfigFileChanged;
				configWatcher.Dispose();
				configWatcher = null;
			}
		}

		private static void SetupFileWatcher()
		{
			configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.heavyintegration.cfg");
			configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
			configWatcher.Changed += OnConfigFileChanged;
			configWatcher.Created += OnConfigFileChanged;
			configWatcher.Renamed += OnConfigFileChanged;
			configWatcher.EnableRaisingEvents = true;
		}

		private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			reloadPending = true;
		}
	}
	public static class HeavyAmmoRegenPatch
	{
		private const float VanillaConversionFactor = 0.015f;

		private static bool loggedLoadout;

		private static bool loggedGrant;

		public static void Apply(Harmony harmony, ManualLogSource log)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(Player), "OnDamagedTarget", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				log.LogError((object)"Could not find Player.OnDamagedTarget — heavy ammo regen disabled.");
				return;
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(HeavyAmmoRegenPatch), "OnDamagedTargetPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			log.LogInfo((object)("Patched " + methodInfo.DeclaringType.Name + "." + methodInfo.Name + " for heavy ammo regen."));
		}

		private static void OnDamagedTargetPostfix(Player __instance, DamageCallbackData data)
		{
			//IL_0036: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (ConfigManager.AmmoRegenEnabled == null || !ConfigManager.AmmoRegenEnabled.Value || (Object)(object)__instance == (Object)null || !Object.op_Implicit((Object)(object)__instance) || !((NetworkBehaviour)__instance).IsOwner || data.source == null || data.damageData.damage <= 0f)
				{
					return;
				}
				float num = ConfigManager.RegenMultiplier?.Value ?? 1f;
				if (num <= 0f)
				{
					return;
				}
				IGear[] gear = __instance.Gear;
				if (gear == null || gear.Length == 0)
				{
					return;
				}
				if (!loggedLoadout)
				{
					loggedLoadout = true;
					LogFullLoadout(__instance, gear, data.damageData.damage);
				}
				IWeapon val = ResolveWeapon(data.source);
				if (val == null || !IsPlayerLoadoutWeapon(__instance, gear, val))
				{
					return;
				}
				float num2 = __instance.upgradeVariables.ammoConversionMultiplier;
				if (num2 <= 0f)
				{
					num2 = 1f;
				}
				float num3 = val.GunData.ammoGenerationEfficiency;
				if (num3 <= 0f)
				{
					num3 = 1f;
				}
				float num4 = data.damageData.damage * num3 * 0.015f * num2 * num;
				float num5 = 3f * num2 * num;
				if (num4 > num5)
				{
					num4 = num5;
				}
				if (num4 <= 0f)
				{
					return;
				}
				foreach (IGear obj in gear)
				{
					Gun val2 = (Gun)(object)((obj is Gun) ? obj : null);
					if (val2 != null && IsHeavy((IGear)(object)val2) && !IsSameWeapon((IGear)(object)val2, val))
					{
						TryGrantMagAmmo(val2, num4);
					}
				}
				IGear heldGear = __instance.HeldGear;
				Gun val3 = (Gun)(object)((heldGear is Gun) ? heldGear : null);
				if (val3 != null && IsHeavy((IGear)(object)val3) && !IsSameWeapon((IGear)(object)val3, val))
				{
					TryGrantMagAmmo(val3, num4);
				}
			}
			catch (Exception arg)
			{
				HeavyIntegrationPlugin.Log.LogError((object)$"Heavy ammo regen error: {arg}");
			}
		}

		internal static bool IsHeavy(IGear gear)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			if (gear == null)
			{
				return false;
			}
			if ((int)((IUpgradable)gear).GearType == 1)
			{
				return true;
			}
			if (((IUpgradable)gear).Prefab != null && (int)((IUpgradable)gear).Prefab.GearType == 1)
			{
				return true;
			}
			return false;
		}

		private static IWeapon ResolveWeapon(IDamageSource source)
		{
			for (IDamageSource val = source; val != null; val = val.ParentSource)
			{
				IWeapon val2 = (IWeapon)(object)((val is IWeapon) ? val : null);
				if (val2 != null)
				{
					return val2;
				}
			}
			return null;
		}

		private static bool IsPlayerLoadoutWeapon(Player player, IGear[] gear, IWeapon weapon)
		{
			if (weapon == null)
			{
				return false;
			}
			for (int i = 0; i < gear.Length; i++)
			{
				if (IsSameWeapon(gear[i], weapon))
				{
					return true;
				}
			}
			if (IsSameWeapon(player.HeldGear, weapon))
			{
				return true;
			}
			IDamageSource val = (IDamageSource)(object)((weapon is IDamageSource) ? weapon : null);
			if (val != null)
			{
				IDamageSource val2 = val.GetBase();
				if ((object)val2 == player || val2 is Player)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsSameWeapon(IGear gear, IWeapon weapon)
		{
			if (gear == null || weapon == null)
			{
				return false;
			}
			if ((object)gear == weapon)
			{
				return true;
			}
			IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null);
			if (val != null && val == weapon)
			{
				return true;
			}
			return false;
		}

		private static void TryGrantMagAmmo(Gun heavy, float density)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)heavy == (Object)null || !Object.op_Implicit((Object)(object)heavy) || !((NetworkBehaviour)heavy).IsOwner)
			{
				return;
			}
			float remainingAmmo = heavy.RemainingAmmo;
			float num = heavy.GunData.magazineSize;
			if (num <= 0f || remainingAmmo >= num)
			{
				return;
			}
			float num2 = Mathf.Min(density, num - remainingAmmo);
			if (!(num2 <= 0f))
			{
				heavy.RemainingAmmo = remainingAmmo + num2;
				if (ConfigManager.PlayAmmoSound != null && ConfigManager.PlayAmmoSound.Value && heavy.RemainingAmmo > remainingAmmo)
				{
					heavy.InvokeOnAmmoRefunded(heavy.RemainingAmmo - remainingAmmo);
				}
				if (!loggedGrant && heavy.RemainingAmmo > remainingAmmo)
				{
					loggedGrant = true;
					HeavyIntegrationPlugin.Log.LogInfo((object)($"Heavy ammo regen OK: +{heavy.RemainingAmmo - remainingAmmo:0.##} on {NameOf((IGear)(object)heavy)} " + $"(GearType={heavy.GearType}, dens={density:0.###}, mag={heavy.RemainingAmmo:0.#}/{num})."));
				}
			}
		}

		private static void LogFullLoadout(Player player, IGear[] gear, float sampleDamage)
		{
			StringBuilder stringBuilder = new StringBuilder(256);
			stringBuilder.Append("Full loadout (heavy detect = GearType.Heavy):");
			for (int i = 0; i < gear.Length; i++)
			{
				stringBuilder.Append(" [").Append(i).Append("]=")
					.Append(Describe(gear[i]));
			}
			if (player.HeldGear != null)
			{
				stringBuilder.Append(" held=").Append(Describe(player.HeldGear));
			}
			stringBuilder.Append(" sampleDmg=").Append(sampleDamage.ToString("0.#"));
			HeavyIntegrationPlugin.Log.LogInfo((object)stringBuilder.ToString());
		}

		private static string Describe(IGear gear)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (gear == null)
			{
				return "null";
			}
			Gun val = (Gun)(object)((gear is Gun) ? gear : null);
			if (val == null || !Object.op_Implicit((Object)(object)val))
			{
				return $"{NameOf(gear)} type={((IUpgradable)gear).GearType} (not Gun)";
			}
			return $"{NameOf((IGear)(object)val)} type={val.GearType} heavy={IsHeavy((IGear)(object)val)} " + $"limited={val.GunData.hasLimitedAmmo} noMagRefill={val.dontRefillMagFromDamage} " + $"eff={val.GunData.ammoGenerationEfficiency} mag={val.RemainingAmmo:0.#}/{val.GunData.magazineSize}";
		}

		private static string NameOf(IGear gear)
		{
			if ((Object)(object)((gear != null) ? ((IUpgradable)gear).Info : null) != (Object)null && !string.IsNullOrEmpty(((IUpgradable)gear).Info.APIName))
			{
				return ((IUpgradable)gear).Info.APIName;
			}
			Component val = (Component)(object)((gear is Component) ? gear : null);
			if (val == null || !((Object)(object)val != (Object)null))
			{
				return ((object)gear)?.GetType().Name ?? "null";
			}
			return ((Object)val).name;
		}
	}
	[HarmonyPatch(typeof(GearSlot))]
	internal static class HeavyFocusPatch
	{
		private static readonly FieldInfo WindowField = AccessTools.Field(typeof(GearSlot), "window");

		[HarmonyPatch("GetAdditionalBinding")]
		[HarmonyPostfix]
		private static void GetAdditionalBindingPostfix(GearSlot __instance, int index, ref InputAction __result, ref string label, ref bool bold)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.HeavyFocusEnabled == null || !ConfigManager.HeavyFocusEnabled.Value || __result != null || ((__instance != null) ? __instance.Gear : null) == null)
			{
				return;
			}
			IUpgradable gear = __instance.Gear;
			if ((int)gear.GearType == 1 && LevelData.CanModifyGear && PlayerData.GetGearData(gear).IsUnlocked && PlayerData.GetPlayerLevel() >= 5)
			{
				object? obj = WindowField?.GetValue(__instance);
				GearSelectionWindow val = (GearSelectionWindow)((obj is GearSelectionWindow) ? obj : null);
				if (val != null && !(((object)val).GetType() == typeof(ShowcaseGearSelectWindow)) && gear.Info.HasWorldPoolUpgrades((Rarity)(-1)))
				{
					label = TextBlocks.GetString("focus");
					bold = false;
					MenuActions menu = PlayerInput.Controls.Menu;
					__result = ((MenuActions)(ref menu)).Favorite;
				}
			}
		}
	}
	internal static class HeavyLoadoutService
	{
		public const int StoredGearIndex = 5;

		public const int StoredSelectedSlot = 6;

		private static readonly FieldInfo GearHudsField = AccessTools.Field(typeof(Player), "gearHUDs");

		private static bool applyInProgress;

		private static int lastApplyFrame = -1;

		private static Coroutine pendingApply;

		internal static bool SuppressReapply;

		private static int managedStoredId;

		public static bool IsEnabled
		{
			get
			{
				if (ConfigManager.LoadoutEnabled != null)
				{
					return ConfigManager.LoadoutEnabled.Value;
				}
				return false;
			}
		}

		public static int SelectedHeavyId => ConfigManager.HeavyGearId?.Value ?? 0;

		public static bool HasSelection => SelectedHeavyId != 0;

		public static void OnConfigReloaded()
		{
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null && ((NetworkBehaviour)localPlayer).IsOwner && localPlayer.IsGearInitialized)
			{
				ScheduleApply(localPlayer);
			}
		}

		public static IUpgradable ResolveSelectedHeavy()
		{
			int selectedHeavyId = SelectedHeavyId;
			if (selectedHeavyId == 0)
			{
				return null;
			}
			return ResolveGearById(selectedHeavyId);
		}

		public static IUpgradable ResolveGearById(int id)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Invalid comparison between Unknown and I4
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Invalid comparison between Unknown and I4
			if (id == 0 || Global.Instance?.AllGear == null)
			{
				return null;
			}
			for (int i = 0; i < Global.Instance.AllGear.Length; i++)
			{
				IUpgradable val = Global.Instance.AllGear[i];
				if ((Object)(object)((val != null) ? val.Info : null) != (Object)null && val.Info.ID == id && (int)val.GearType == 1)
				{
					return val;
				}
			}
			try
			{
				GearData gearData = PlayerData.GetGearData(id);
				if (((gearData != null) ? gearData.Gear : null) != null && (int)gearData.Gear.GearType == 1)
				{
					return gearData.Gear;
				}
			}
			catch
			{
			}
			return null;
		}

		public static bool IsLoadoutHeavy(IUpgradable gear)
		{
			if (gear == null || !HasSelection)
			{
				return false;
			}
			IUpgradable val = gear.GetPrefab() ?? gear;
			if ((Object)(object)val.Info != (Object)null)
			{
				return val.Info.ID == SelectedHeavyId;
			}
			return false;
		}

		public static bool IsSamePrefab(IGear live, IUpgradable desired)
		{
			if (live == null || desired == null)
			{
				return false;
			}
			IUpgradable val = (IUpgradable)(((object)((IUpgradable)live).Prefab) ?? ((object)live));
			IUpgradable val2 = desired.GetPrefab() ?? desired;
			if (val == val2)
			{
				return true;
			}
			if ((Object)(object)((val != null) ? val.Info : null) != (Object)null && (Object)(object)((val2 != null) ? val2.Info : null) != (Object)null)
			{
				return val.Info.ID == val2.Info.ID;
			}
			return false;
		}

		private static int GetPrefabId(IGear gear)
		{
			if (gear == null)
			{
				return 0;
			}
			object obj = ((object)((IUpgradable)gear).Prefab) ?? ((object)gear);
			int? obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				GearInfo info = ((IUpgradable)obj).Info;
				obj2 = ((info != null) ? new int?(info.ID) : ((int?)null));
			}
			int? num = obj2;
			return num.GetValueOrDefault();
		}

		public static void SelectOrToggleHeavy(IUpgradable gear)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if (!IsEnabled || gear == null || (int)gear.GearType != 1)
			{
				return;
			}
			if (!PlayerData.IsGearUnlocked(gear))
			{
				ManualLogSource log = HeavyIntegrationPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Cannot set locked heavy as loadout heavy.");
				}
				return;
			}
			IUpgradable val = gear.GetPrefab() ?? gear;
			GearInfo info = val.Info;
			int num = ((info != null) ? info.ID : 0);
			if (num == 0)
			{
				return;
			}
			if (SelectedHeavyId == num)
			{
				ConfigManager.SetHeavyGearId(0);
				ManualLogSource log2 = HeavyIntegrationPlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"Cleared loadout heavy.");
				}
			}
			else
			{
				ConfigManager.SetHeavyGearId(num);
				ManualLogSource log3 = HeavyIntegrationPlugin.Log;
				if (log3 != null)
				{
					GearInfo info2 = val.Info;
					object obj = ((info2 != null) ? info2.APIName : null);
					if (obj == null)
					{
						GearInfo info3 = val.Info;
						obj = ((info3 != null) ? info3.Name : null);
					}
					log3.LogInfo((object)$"Loadout heavy set to '{obj}' (id={num}).");
				}
			}
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null && ((NetworkBehaviour)localPlayer).IsOwner && localPlayer.IsGearInitialized)
			{
				ScheduleApply(localPlayer);
			}
		}

		public static void ScheduleApply(Player player, int delayFrames = 1)
		{
			if ((Object)(object)player == (Object)null || !((NetworkBehaviour)player).IsOwner)
			{
				return;
			}
			if (pendingApply != null)
			{
				try
				{
					((MonoBehaviour)player).StopCoroutine(pendingApply);
				}
				catch
				{
				}
				pendingApply = null;
			}
			pendingApply = ((MonoBehaviour)player).StartCoroutine(ApplyAfterFrames(player, delayFrames));
		}

		private static IEnumerator ApplyAfterFrames(Player player, int delayFrames)
		{
			for (int i = 0; i < delayFrames; i++)
			{
				yield return null;
			}
			pendingApply = null;
			TryApply(player);
		}

		public static void TryApply(Player player)
		{
			if (!IsEnabled || (Object)(object)player == (Object)null || !((NetworkBehaviour)player).IsOwner || !player.IsGearInitialized || applyInProgress || Time.frameCount == lastApplyFrame || Global.Instance?.AllGear == null || player.Gear == null || player.Gear.Length <= 5)
			{
				return;
			}
			applyInProgress = true;
			lastApplyFrame = Time.frameCount;
			try
			{
				IUpgradable val = ResolveSelectedHeavy();
				IGear val2 = player.Gear[5];
				int prefabId = GetPrefabId(val2);
				if (val == null)
				{
					if (val2 != null && managedStoredId != 0 && prefabId == managedStoredId)
					{
						ClearStoredManaged(player);
					}
					else if (val2 == null)
					{
						managedStoredId = 0;
					}
				}
				else if (!PlayerData.IsGearUnlocked(val))
				{
					ManualLogSource log = HeavyIntegrationPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)$"Loadout heavy id={SelectedHeavyId} is not unlocked — skip apply.");
					}
				}
				else
				{
					if (val2 != null && !IsSamePrefab(val2, val) && (managedStoredId == 0 || prefabId != managedStoredId))
					{
						return;
					}
					if (IsSamePrefab(val2, val))
					{
						managedStoredId = val.Info.ID;
						EnsureStoredHudVisible(player, val2);
						return;
					}
					int num = Array.IndexOf(Global.Instance.AllGear, val);
					if (num < 0)
					{
						num = FindAllGearIndexById(val.Info.ID);
					}
					if (num < 0)
					{
						ManualLogSource log2 = HeavyIntegrationPlugin.Log;
						if (log2 != null)
						{
							GearInfo info = val.Info;
							log2.LogWarning((object)("Loadout heavy '" + ((info != null) ? info.APIName : null) + "' not found in AllGear."));
						}
						return;
					}
					bool flag = val2 != null;
					SuppressReapply = true;
					try
					{
						if (val2 != null)
						{
							bool flag2 = false;
							try
							{
								flag2 = (Object)(object)val2.AsNetworkBehaviour() != (Object)null;
							}
							catch
							{
								flag2 = false;
							}
							if (!flag2)
							{
								try
								{
									player.DropStoredGear();
									flag = false;
								}
								catch (Exception ex)
								{
									ManualLogSource log3 = HeavyIntegrationPlugin.Log;
									if (log3 != null)
									{
										log3.LogWarning((object)("DropStoredGear before apply: " + ex.Message));
									}
								}
							}
						}
						player.SpawnGear_ServerRpc(5, num, false, flag);
						managedStoredId = val.Info.ID;
						ManualLogSource log4 = HeavyIntegrationPlugin.Log;
						if (log4 != null)
						{
							GearInfo info2 = val.Info;
							log4.LogInfo((object)("Spawned loadout heavy '" + ((info2 != null) ? info2.APIName : null) + "' into stored slot."));
						}
					}
					finally
					{
						SuppressReapply = false;
					}
					ScheduleHudRefresh(player);
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log5 = HeavyIntegrationPlugin.Log;
				if (log5 != null)
				{
					log5.LogError((object)$"Apply loadout heavy failed: {arg}");
				}
			}
			finally
			{
				applyInProgress = false;
			}
		}

		public static void OnStoredCleared(Player player)
		{
			if (!SuppressReapply && IsEnabled)
			{
				managedStoredId = 0;
				if (ConfigManager.ReapplyAfterDrop != null && ConfigManager.ReapplyAfterDrop.Value && !((Object)(object)player == (Object)null) && ((NetworkBehaviour)player).IsOwner && HasSelection)
				{
					ScheduleApply(player, 2);
				}
			}
		}

		public static void OnReplaceStored(Player player, IGear gear)
		{
			if (!((Object)(object)player == (Object)null) && ((NetworkBehaviour)player).IsOwner)
			{
				int prefabId = GetPrefabId(gear);
				if (prefabId != 0 && prefabId == SelectedHeavyId)
				{
					managedStoredId = prefabId;
				}
				else
				{
					managedStoredId = 0;
				}
			}
		}

		private static void ClearStoredManaged(Player player)
		{
			SuppressReapply = true;
			try
			{
				IGear val = player.Gear[5];
				if (val != null)
				{
					bool flag = false;
					try
					{
						flag = (Object)(object)val.AsNetworkBehaviour() != (Object)null;
					}
					catch
					{
						flag = false;
					}
					if (flag)
					{
						player.DespawnGear_ServerRpc(5);
					}
					else
					{
						player.DropStoredGear();
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = HeavyIntegrationPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Clear stored loadout heavy: " + ex.Message));
				}
			}
			finally
			{
				managedStoredId = 0;
				SuppressReapply = false;
			}
			SetStoredHudActive(player, active: false);
		}

		private static int FindAllGearIndexById(int id)
		{
			if (Global.Instance?.AllGear == null)
			{
				return -1;
			}
			for (int i = 0; i < Global.Instance.AllGear.Length; i++)
			{
				IUpgradable val = Global.Instance.AllGear[i];
				if ((Object)(object)((val != null) ? val.Info : null) != (Object)null && val.Info.ID == id)
				{
					return i;
				}
			}
			return -1;
		}

		private static void ScheduleHudRefresh(Player player)
		{
			((MonoBehaviour)player).StartCoroutine(HudRefreshNextFrame(player));
		}

		private static IEnumerator HudRefreshNextFrame(Player player)
		{
			yield return null;
			yield return null;
			if (!((Object)(object)player == (Object)null) && player.Gear != null && player.Gear.Length > 5)
			{
				IGear val = player.Gear[5];
				if (val != null)
				{
					EnsureStoredHudVisible(player, val);
				}
			}
		}

		internal static void EnsureStoredHudVisible(Player player, IGear gear)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || gear == null)
			{
				return;
			}
			try
			{
				if (GearHudsField?.GetValue(player) is EquippableHUDOverlay[] array && array.Length >= 3 && !((Object)(object)array[2] == (Object)null))
				{
					if (!((Component)array[2]).gameObject.activeSelf)
					{
						((Component)array[2]).gameObject.SetActive(true);
					}
					array[2].Setup(gear, array[2].BasePos);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = HeavyIntegrationPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Stored HUD setup failed: " + ex.Message));
				}
			}
		}

		private static void SetStoredHudActive(Player player, bool active)
		{
			try
			{
				if (GearHudsField?.GetValue(player) is EquippableHUDOverlay[] array && array.Length >= 3 && !((Object)(object)array[2] == (Object)null))
				{
					((Component)array[2]).gameObject.SetActive(active);
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(ScrollArea), "Scroll")]
	internal static class ScrollAreaNullGuard
	{
		[HarmonyPrefix]
		private static bool Prefix(ScrollArea __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return false;
				}
				if ((Object)(object)Traverse.Create((object)__instance).Field("scrollBar").GetValue<ScrollBar>() == (Object)null)
				{
					return false;
				}
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(WeaponSelectWindow), "Setup")]
	internal static class WeaponSelectWindowSetupPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(WeaponSelectWindow __instance, GearType type)
		{
			if (ConfigManager.SelectionUiEnabled == null || !ConfigManager.SelectionUiEnabled.Value)
			{
				return true;
			}
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return false;
				}
				List<GearSlot> value = Traverse.Create((object)__instance).Field("gearSlots").GetValue<List<GearSlot>>();
				if (value == null || value.Count == 0 || (Object)(object)value[0] == (Object)null)
				{
					ManualLogSource log = HeavyIntegrationPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"WeaponSelectWindow has no gearSlots prefab — skipping Setup.");
					}
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = HeavyIntegrationPlugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("WeaponSelectWindow Setup prefix: " + ex.Message));
				}
				return true;
			}
		}

		[HarmonyPostfix]
		private static void Postfix(WeaponSelectWindow __instance, GearType type)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.SelectionUiEnabled == null || !ConfigManager.SelectionUiEnabled.Value)
			{
				return;
			}
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				List<GearSlot> value = Traverse.Create((object)__instance).Field("gearSlots").GetValue<List<GearSlot>>();
				if (value == null || value.Count == 0)
				{
					return;
				}
				int num = CountUnlockedOfType(type);
				if (num < 0)
				{
					return;
				}
				for (int i = 0; i < value.Count; i++)
				{
					if (!((Object)(object)value[i] == (Object)null) && !((Object)(object)((Component)value[i]).gameObject == (Object)null))
					{
						((Component)value[i]).gameObject.SetActive(i < num);
					}
				}
				if (num > 0)
				{
					WeaponSelectOverflow.Apply(__instance, value, num);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = HeavyIntegrationPlugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("WeaponSelectWindow Setup postfix: " + ex.Message));
				}
			}
		}

		private static int CountUnlockedOfType(GearType type)
		{
			//IL_0009: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<IUpgradable> list = new List<IUpgradable>(16);
				GearSelectionWindow.GetSortedUnlockedGear(list, type, false);
				int num = 0;
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i] != null && list[i].GearType == type)
					{
						num++;
					}
				}
				return num;
			}
			catch
			{
				return -1;
			}
		}
	}
	[HarmonyPatch(typeof(GearSlot))]
	internal static class GearSlotClickPatch
	{
		private static readonly FieldInfo SlotField = AccessTools.Field(typeof(GearSlot), "slot");

		private static readonly FieldInfo ButtonField = AccessTools.Field(typeof(GearSlot), "button");

		[HarmonyPatch("OnClick")]
		[HarmonyPrefix]
		private static bool OnClickPrefix(GearSlot __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!HeavyLoadoutService.IsEnabled || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			IUpgradable gear = __instance.Gear;
			if (gear == null || (int)gear.GearType != 1)
			{
				return true;
			}
			int num = ((SlotField != null) ? ((int)SlotField.GetValue(__instance)) : (-1));
			object? obj = ButtonField?.GetValue(__instance);
			DefaultButton val = (DefaultButton)((obj is DefaultButton) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if ((int)((Button)val).LastPressButton == 1)
			{
				return true;
			}
			if ((int)((Button)val).LastPressButton != 0)
			{
				return true;
			}
			if (!PlayerData.GetGearData(gear).IsUnlocked && num < 0)
			{
				return true;
			}
			if (num < 0)
			{
				HeavyLoadoutService.SelectOrToggleHeavy(gear);
				return false;
			}
			return true;
		}

		[HarmonyPatch("GetPrimaryBinding")]
		[HarmonyPostfix]
		private static void GetPrimaryBindingPostfix(GearSlot __instance, ref bool __result, ref InputAction binding, ref string label)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (HeavyLoadoutService.IsEnabled && ((__instance != null) ? __instance.Gear : null) != null && (int)__instance.Gear.GearType == 1 && ((SlotField != null) ? ((int)SlotField.GetValue(__instance)) : (-1)) < 0 && PlayerData.GetGearData(__instance.Gear).IsUnlocked)
			{
				MenuActions menu = PlayerInput.Controls.Menu;
				binding = ((MenuActions)(ref menu)).Click;
				bool flag = HeavyLoadoutService.IsLoadoutHeavy(__instance.Gear);
				label = (flag ? "Clear" : TextBlocks.GetString("equip"));
				if (string.IsNullOrEmpty(label) || label == "equip")
				{
					label = (flag ? "Clear" : "Equip");
				}
				__result = true;
			}
		}
	}
	[HarmonyPatch]
	internal static class GearSelectionWindowPatch
	{
		[HarmonyPatch(typeof(GearSelectionWindow), "OnCloseCallback")]
		[HarmonyPostfix]
		private static void OnClosePostfix()
		{
			if (HeavyLoadoutService.IsEnabled)
			{
				Player localPlayer = Player.LocalPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && ((NetworkBehaviour)localPlayer).IsOwner && localPlayer.IsGearInitialized)
				{
					HeavyLoadoutService.ScheduleApply(localPlayer);
				}
			}
		}

		[HarmonyPatch(typeof(ShowcaseGearSelectWindow), "OnCloseCallback")]
		[HarmonyPostfix]
		private static void ShowcaseClosePostfix()
		{
			if (HeavyLoadoutService.IsEnabled)
			{
				Player localPlayer = Player.LocalPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && ((NetworkBehaviour)localPlayer).IsOwner && localPlayer.IsGearInitialized)
				{
					HeavyLoadoutService.ScheduleApply(localPlayer, 2);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class PlayerGearPatches
	{
		[HarmonyPatch(typeof(Player), "OnAllGearSpawned_ClientRpc")]
		[HarmonyPostfix]
		private static void OnAllGearSpawnedPostfix(Player __instance)
		{
			if (HeavyLoadoutService.IsEnabled && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.IsGearInitialized)
			{
				HeavyLoadoutService.ScheduleApply(__instance, 2);
			}
		}

		[HarmonyPatch(typeof(Player), "SpawnGear_ClientRpc")]
		[HarmonyPostfix]
		private static void SpawnGearClientPostfix(Player __instance, int slot)
		{
			if (HeavyLoadoutService.IsEnabled && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && slot == 5 && __instance.Gear != null && slot < __instance.Gear.Length)
			{
				IGear val = __instance.Gear[slot];
				if (val != null)
				{
					HeavyLoadoutService.EnsureStoredHudVisible(__instance, val);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "DropStoredGear")]
		[HarmonyPostfix]
		private static void DropStoredPostfix(Player __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner)
			{
				HeavyLoadoutService.OnStoredCleared(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "OnGearRemoved")]
		[HarmonyPostfix]
		private static void OnGearRemovedPostfix(Player __instance, IGear gear)
		{
			if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && gear != null && __instance.Gear != null && __instance.Gear.Length > 5 && __instance.Gear[5] == null)
			{
				HeavyLoadoutService.OnStoredCleared(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "OnStoredGearRemoved")]
		[HarmonyPostfix]
		private static void OnStoredGearRemovedPostfix(Player __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner)
			{
				HeavyLoadoutService.OnStoredCleared(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "ReplaceStoredGear")]
		[HarmonyPostfix]
		private static void ReplaceStoredPostfix(Player __instance, IGear gear)
		{
			if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner)
			{
				HeavyLoadoutService.OnReplaceStored(__instance, gear);
			}
		}
	}
	[BepInPlugin("sparroh.heavyintegration", "HeavyIntegration", "1.0.0")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class HeavyIntegrationPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "sparroh.heavyintegration";

		public const string PluginName = "HeavyIntegration";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Log);
				_harmony = new Harmony("sparroh.heavyintegration");
				_harmony.PatchAll(typeof(GearSlotClickPatch));
				_harmony.PatchAll(typeof(GearSelectionWindowPatch));
				_harmony.PatchAll(typeof(PlayerGearPatches));
				_harmony.PatchAll(typeof(HeavyFocusPatch));
				HeavyAmmoRegenPatch.Apply(_harmony, Log);
				_harmony.PatchAll(typeof(ScrollAreaNullGuard));
				_harmony.PatchAll(typeof(WeaponSelectWindowSetupPatch));
				Log.LogInfo((object)"HeavyIntegration v1.0.0 loaded — loadout heavy, ammo regen, heavy focus, selection UI.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("Failed to initialize {0}: {1}", "HeavyIntegration", arg));
			}
		}

		private void Update()
		{
			ConfigManager.Tick();
		}

		private void OnDestroy()
		{
			try
			{
				ConfigManager.Dispose();
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)string.Format("Failed to tear down {0}: {1}", "HeavyIntegration", arg));
				}
			}
		}
	}
	internal static class WeaponSelectOverflow
	{
		private const float FallbackPadding = 10f;

		private const float TopPadding = 6f;

		private const float MinStepFactor = 0.5f;

		private static readonly Dictionary<int, Vector2> PrefabRest = new Dictionary<int, Vector2>(4);

		private static RectTransform _boundContainer;

		private static float _boundMaxScroll;

		private static float _boundContentX;

		private static float _boundRestY;

		public static void Apply(WeaponSelectWindow window, List<GearSlot> slots, int activeCount)
		{
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window == (Object)null || slots == null || activeCount <= 0)
			{
				return;
			}
			GearSlot val = slots[0];
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)val).transform.parent;
			RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)val2).GetInstanceID();
			if (!PrefabRest.TryGetValue(instanceID, out var value))
			{
				value = val2.anchoredPosition;
				PrefabRest[instanceID] = value;
			}
			val2.anchoredPosition = value;
			if (!TryMeasureLayout(slots, activeCount, out var originX, out var originY, out var stepY, out var slotHeight))
			{
				return;
			}
			LayoutGroup component = ((Component)val2).GetComponent<LayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			float contentHeight = slotHeight + stepY * (float)Mathf.Max(activeCount - 1, 0);
			RectTransform val3 = ResolveViewport(window, val2, contentHeight);
			if ((Object)(object)val3 == (Object)null)
			{
				Transform transform = ((Component)window).transform;
				val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			}
			EnsureRectMask(val3);
			for (int i = 0; i < activeCount; i++)
			{
				GearSlot val4 = slots[i];
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				Transform transform2 = ((Component)val4).transform;
				RectTransform val5 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
				if (!((Object)(object)val5 == (Object)null))
				{
					val5.anchoredPosition = new Vector2(originX, originY - stepY * (float)i);
					if (!((Component)val4).gameObject.activeSelf)
					{
						((Component)val4).gameObject.SetActive(true);
					}
				}
			}
			Canvas.ForceUpdateCanvases();
			Vector2 val6 = AlignFirstSlotToViewportTop(slots[0], val2, val3, value.x);
			Canvas.ForceUpdateCanvases();
			float num = ComputeMaxScroll(slots, activeCount, val3, val2, val6);
			ScrollArea componentInChildren = ((Component)window).GetComponentInChildren<ScrollArea>(true);
			ScrollBar val7 = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.ScrollBar : null);
			if ((Object)(object)val7 == (Object)null)
			{
				val7 = ((Component)window).GetComponentInChildren<ScrollBar>(true);
			}
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)val7 != (Object)null)
			{
				try
				{
					componentInChildren.ItemContainer = val2;
					Traverse.Create((object)componentInChildren).Field("autoScrollContainer").SetValue((object)val2);
					val7.OnDrag.RemoveListener((UnityAction<Vector2>)OnExistingBarDrag);
					_boundContainer = val2;
					_boundMaxScroll = num;
					_boundContentX = val6.x;
					_boundRestY = val6.y;
					val7.OnDrag.AddListener((UnityAction<Vector2>)OnExistingBarDrag);
					if (num <= 0f)
					{
						val7.ScrollSpeed = 0f;
					}
					else
					{
						val7.ScrollSpeed = 475f / num * 0.001f;
					}
					val2.anchoredPosition = val6;
					val7.SetScrollYNoInvoke(1f);
				}
				catch (Exception ex)
				{
					ManualLogSource log = HeavyIntegrationPlugin.Log;
					if (log != null)
					{
						log.LogDebug((object)("ScrollArea wire failed: " + ex.Message));
					}
					AttachFallbackDriver(window, val3, val2, num, val6);
				}
			}
			else
			{
				AttachFallbackDriver(window, val3, val2, num, val6);
			}
			EnsureRaycastTarget(val3);
		}

		private static void OnExistingBarDrag(Vector2 value)
		{
			//IL_001e: 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)
			if (!((Object)(object)_boundContainer == (Object)null))
			{
				float num = Mathf.LerpUnclamped(_boundRestY + _boundMaxScroll, _boundRestY, value.y);
				_boundContainer.anchoredPosition = new Vector2(_boundContentX, num);
			}
		}

		private static bool TryMeasureLayout(List<GearSlot> slots, int activeCount, out float originX, out float originY, out float stepY, out float slotHeight)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			originX = 0f;
			originY = 0f;
			stepY = 0f;
			slotHeight = 0f;
			Transform transform = ((Component)slots[0]).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			originX = val.anchoredPosition.x;
			originY = val.anchoredPosition.y;
			Rect rect = val.rect;
			slotHeight = Mathf.Max(((Rect)(ref rect)).height, Mathf.Abs(val.sizeDelta.y));
			if (slotHeight < 1f)
			{
				slotHeight = 80f;
			}
			stepY = 0f;
			for (int i = 1; i < slots.Count && i < activeCount; i++)
			{
				if ((Object)(object)slots[i] == (Object)null)
				{
					continue;
				}
				Transform transform2 = ((Component)slots[i]).transform;
				RectTransform val2 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					float num = originY - val2.anchoredPosition.y;
					if (num > slotHeight * 0.5f)
					{
						stepY = num;
						break;
					}
				}
			}
			if (stepY < 1f)
			{
				stepY = slotHeight + 10f;
			}
			return true;
		}

		private static Vector2 AlignFirstSlotToViewportTop(GearSlot first, RectTransform slotParent, RectTransform viewport, float contentX)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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)
			//IL_008e: 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_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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0100: 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)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			Vector2 anchoredPosition = slotParent.anchoredPosition;
			anchoredPosition.x = contentX;
			slotParent.anchoredPosition = anchoredPosition;
			if ((Object)(object)first == (Object)null || (Object)(object)viewport == (Object)null || (Object)(object)slotParent == (Object)(object)viewport)
			{
				return slotParent.anchoredPosition;
			}
			Transform transform = ((Component)first).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val == (Object)null)
			{
				return slotParent.anchoredPosition;
			}
			Canvas.ForceUpdateCanvases();
			float rectEdgeInOther = GetRectEdgeInOther(val, viewport, top: true);
			Rect rect = viewport.rect;
			if (Mathf.Abs(((Rect)(ref rect)).yMax - 6f - rectEdgeInOther) > 0.5f)
			{
				rect = val.rect;
				float x = ((Rect)(ref rect)).center.x;
				rect = val.rect;
				Vector3 val2 = ((Transform)val).TransformPoint(new Vector3(x, ((Rect)(ref rect)).yMax, 0f));
				rect = viewport.rect;
				float x2 = ((Rect)(ref rect)).center.x;
				rect = viewport.rect;
				Vector3 val3 = ((Transform)viewport).TransformPoint(new Vector3(x2, ((Rect)(ref rect)).yMax - 6f, 0f)) - val2;
				Vector3 up = ((Transform)slotParent).up;
				float num = Vector3.Dot(val3, up);
				float y = ((Transform)slotParent).lossyScale.y;
				if (Mathf.Abs(y) > 0.0001f)
				{
					num /= y;
				}
				anchoredPosition = slotParent.anchoredPosition;
				anchoredPosition.y += num;
				anchoredPosition.x = contentX;
				slotParent.anchoredPosition = anchoredPosition;
			}
			return slotParent.anchoredPosition;
		}

		private static float GetRectEdgeInOther(RectTransform source, RectTransform other, bool top)
		{
			//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_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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Rect rect;
			float num;
			if (!top)
			{
				rect = source.rect;
				num = ((Rect)(ref rect)).yMin;
			}
			else
			{
				rect = source.rect;
				num = ((Rect)(ref rect)).yMax;
			}
			float num2 = num;
			rect = source.rect;
			Vector3 val = ((Transform)source).TransformPoint(new Vector3(((Rect)(ref rect)).center.x, num2, 0f));
			return ((Transform)other).InverseTransformPoint(val).y;
		}

		private static float ComputeMaxScroll(List<GearSlot> slots, int activeCount, RectTransform viewport, RectTransform slotParent, Vector2 restPos)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)viewport == (Object)null || (Object)(object)slotParent == (Object)null || activeCount <= 0)
			{
				return 0f;
			}
			GearSlot val = null;
			for (int num = activeCount - 1; num >= 0; num--)
			{
				if ((Object)(object)slots[num] != (Object)null && (Object)(object)((Component)slots[num]).gameObject != (Object)null && ((Component)slots[num]).gameObject.activeSelf)
				{
					val = slots[num];
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return 0f;
			}
			Transform transform = ((Component)val).transform;
			RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return 0f;
			}
			slotParent.anchoredPosition = restPos;
			Canvas.ForceUpdateCanvases();
			Rect rect;
			if ((Object)(object)viewport == (Object)(object)slotParent)
			{
				float[] array = new float[3];
				rect = val2.rect;
				array[0] = ((Rect)(ref rect)).height;
				array[1] = Mathf.Abs(val2.sizeDelta.y);
				array[2] = 1f;
				float num2 = Mathf.Max(array);
				float num3 = 0f - val2.anchoredPosition.y + num2;
				rect = viewport.rect;
				return Mathf.Max(num3 - ((Rect)(ref rect)).height + 10f, 0f);
			}
			float rectEdgeInOther = GetRectEdgeInOther(val2, viewport, top: false);
			rect = viewport.rect;
			return Mathf.Max(((Rect)(ref rect)).yMin - rectEdgeInOther + 10f, 0f);
		}

		private static RectTransform ResolveViewport(WeaponSelectWindow window, RectTransform slotParent, float contentHeight)
		{
			//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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (Transform)(object)slotParent;
			int num = 0;
			Rect rect;
			while ((Object)(object)val != (Object)null && num < 10)
			{
				RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null);
				if (val2 != null && (Object)(object)val != (Object)(object)slotParent)
				{
					rect = val2.rect;
					if (((Rect)(ref rect)).height > 40f && ((Object)(object)((Component)val2).GetComponent<RectMask2D>() != (Object)null || (Object)(object)((Component)val2).GetComponent<Mask>() != (Object)null))
					{
						return val2;
					}
				}
				if ((Object)(object)val == (Object)(object)((Component)window).transform)
				{
					break;
				}
				val = val.parent;
				num++;
			}
			RectTransform val3 = null;
			val = ((Transform)slotParent).parent;
			num = 0;
			while ((Object)(object)val != (Object)null && num < 8)
			{
				RectTransform val4 = (RectTransform)(object)((val is RectTransform) ? val : null);
				if (val4 != null)
				{
					rect = val4.rect;
					if (((Rect)(ref rect)).height > 40f)
					{
						if (contentHeight > 0f)
						{
							rect = val4.rect;
							if (((Rect)(ref rect)).height + 1f < contentHeight)
							{
								return val4;
							}
						}
						if ((Object)(object)val3 == (Object)null)
						{
							val3 = val4;
						}
					}
				}
				if ((Object)(object)val == (Object)(object)((Component)window).transform)
				{
					break;
				}
				val = val.parent;
				num++;
			}
			if ((Object)(object)val3 != (Object)null)
			{
				return val3;
			}
			Transform transform = ((Component)window).transform;
			return (RectTransform)(object)((transform is RectTransform) ? transform : null);
		}

		private static void EnsureRectMask(RectTransform viewport)
		{
			if (!((Object)(object)viewport == (Object)null) && (Object)(object)((Component)viewport).GetComponent<RectMask2D>() == (Object)null && (Object)(object)((Component)viewport).GetComponent<Mask>() == (Object)null)
			{
				((Component)viewport).gameObject.AddComponent<RectMask2D>();
			}
		}

		private static void EnsureRaycastTarget(RectTransform viewport)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)viewport == (Object)null))
			{
				Graphic component = ((Component)viewport).GetComponent<Graphic>();
				if ((Object)(object)component == (Object)null)
				{
					Image obj = ((Component)viewport).gameObject.AddComponent<Image>();
					((Graphic)obj).color = new Color(0f, 0f, 0f, 0f);
					((Graphic)obj).raycastTarget = true;
				}
				else
				{
					component.raycastTarget = true;
				}
			}
		}

		private static void AttachFallbackDriver(WeaponSelectWindow window, RectTransform viewport, RectTransform content, float maxScroll, Vector2 restPos)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			WeaponSelectScrollDriver weaponSelectScrollDriver = ((Component)window).GetComponent<WeaponSelectScrollDriver>();
			if ((Object)(object)weaponSelectScrollDriver == (Object)null)
			{
				weaponSelectScrollDriver = ((Component)window).gameObject.AddComponent<WeaponSelectScrollDriver>();
			}
			weaponSelectScrollDriver.Configure(viewport, content, maxScroll, restPos);
		}
	}
	internal sealed class WeaponSelectScrollDriver : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		private RectTransform _viewport;

		private RectTransform _content;

		private float _maxScroll;

		private float _contentX;

		private float _restY;

		private float _normalized = 1f;

		private bool _hovering;

		private Action<CallbackContext> _onScrollCallback;

		public void Configure(RectTransform viewport, RectTransform content, float maxScroll, Vector2 restPos)
		{
			//IL_0020: 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)
			_viewport = viewport;
			_content = content;
			_maxScroll = Mathf.Max(0f, maxScroll);
			_contentX = restPos.x;
			_restY = restPos.y;
			_normalized = 1f;
			ApplyPosition();
			if ((Object)(object)_viewport != (Object)null)
			{
				WeaponSelectScrollViewportProxy weaponSelectScrollViewportProxy = ((Component)_viewport).GetComponent<WeaponSelectScrollViewportProxy>();
				if ((Object)(object)weaponSelectScrollViewportProxy == (Object)null)
				{
					weaponSelectScrollViewportProxy = ((Component)_viewport).gameObject.AddComponent<WeaponSelectScrollViewportProxy>();
				}
				weaponSelectScrollViewportProxy.Bind(this);
			}
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			SetHovering(hovering: true);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			SetHovering(hovering: false);
		}

		internal void SetHovering(bool hovering)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (_hovering != hovering)
			{
				_hovering = hovering;
				EnsureScrollCallback();
				MenuActions menu;
				if (_hovering)
				{
					menu = PlayerInput.Controls.Menu;
					((MenuActions)(ref menu)).ScrollWheel.performed += _onScrollCallback;
				}
				else
				{
					menu = PlayerInput.Controls.Menu;
					((MenuActions)(ref menu)).ScrollWheel.performed -= _onScrollCallback;
				}
			}
		}

		private void OnDisable()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (_onScrollCallback != null)
			{
				MenuActions menu = PlayerInput.Controls.Menu;
				((MenuActions)(ref menu)).ScrollWheel.performed -= _onScrollCallback;
			}
			_hovering = false;
		}

		private void OnDestroy()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (_onScrollCallback != null)
			{
				try
				{
					MenuActions menu = PlayerInput.Controls.Menu;
					((MenuActions)(ref menu)).ScrollWheel.performed -= _onScrollCallback;
				}
				catch
				{
				}
			}
		}

		private void EnsureScrollCallback()
		{
			if (_onScrollCallback == null)
			{
				_onScrollCallback = OnScrollPerformed;
			}
		}

		private void OnScrollPerformed(CallbackContext context)
		{
			//IL_0016: 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_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_004a: Unknown result type (might be due to invalid IL or missing references)
			if (_hovering && !(_maxScroll <= 0f) && (int)PlayerInput.Device == 0)
			{
				Vector2 val = ((CallbackContext)(ref context)).ReadValue<Vector2>() * 120f;
				float num = 475f / _maxScroll * 0.001f;
				_normalized = Mathf.Clamp01(_normalized + val.y * num);
				ApplyPosition();
			}
		}

		private void Update()
		{
			//IL_0016: 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_0028: 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_0036: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			if (_hovering && !(_maxScroll <= 0f) && (int)PlayerInput.Device != 0)
			{
				MenuActions menu = PlayerInput.Controls.Menu;
				Vector2 val = ((MenuActions)(ref menu)).ScrollWheel.ReadValue<Vector2>();
				if (!(val == default(Vector2)))
				{
					Vector2 val2 = val * (Time.unscaledDeltaTime * 1000f * 120f);
					float num = 475f / _maxScroll * 0.001f;
					_normalized = Mathf.Clamp01(_normalized + val2.y * num);
					ApplyPosition();
				}
			}
		}

		private void ApplyPosition()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_content == (Object)null))
			{
				float num = ((_maxScroll <= 0f) ? _restY : Mathf.LerpUnclamped(_restY + _maxScroll, _restY, _normalized));
				_content.anchoredPosition = new Vector2(_contentX, num);
			}
		}
	}
	internal sealed class WeaponSelectScrollViewportProxy : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		private WeaponSelectScrollDriver _driver;

		public void Bind(WeaponSelectScrollDriver driver)
		{
			_driver = driver;
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			_driver?.SetHovering(hovering: true);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			_driver?.SetHovering(hovering: false);
		}

		private void OnDisable()
		{
			_driver?.SetHovering(hovering: false);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "HeavyIntegration";

		public const string PLUGIN_NAME = "HeavyIntegration";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}