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 LoadoutEnabled { get; private set; } public static ConfigEntry HeavyGearId { get; private set; } public static ConfigEntry ReapplyAfterDrop { get; private set; } public static ConfigEntry AmmoRegenEnabled { get; private set; } public static ConfigEntry RegenMultiplier { get; private set; } public static ConfigEntry PlayAmmoSound { get; private set; } public static ConfigEntry HeavyFocusEnabled { get; private set; } public static ConfigEntry SelectionUiEnabled { get; private set; } public static void Initialize(ConfigFile configFile, ManualLogSource log) { config = configFile; logger = log; LoadoutEnabled = config.Bind("Loadout", "Enabled", true, "When enabled, the selected heavy weapon is kept in your stored (heavy) loadout slot."); HeavyGearId = config.Bind("Loadout", "Heavy Gear Id", 0, "GearInfo.ID of the loadout heavy weapon. 0 = none (empty). Prefer selecting in the gear menu."); ReapplyAfterDrop = config.Bind("Loadout", "Reapply After Drop", true, "When true, dropping or clearing a temporary stored pickup restores your loadout heavy."); AmmoRegenEnabled = config.Bind("Ammo Regen", "Enable Feature", true, "When enabled, heavy weapons gain magazine ammo from damage dealt by your other main weapon."); RegenMultiplier = config.Bind("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("Ammo Regen", "Play Ammo Sound", false, "Play the ammo refund sound when heavy magazine ammo is restored from damage."); HeavyFocusEnabled = config.Bind("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("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() == (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 value = Traverse.Create((object)__instance).Field("gearSlots").GetValue>(); 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 value = Traverse.Create((object)__instance).Field("gearSlots").GetValue>(); 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 list = new List(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 PrefabRest = new Dictionary(4); private static RectTransform _boundContainer; private static float _boundMaxScroll; private static float _boundContentX; private static float _boundRestY; public static void Apply(WeaponSelectWindow window, List 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(); 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(true); ScrollBar val7 = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.ScrollBar : null); if ((Object)(object)val7 == (Object)null) { val7 = ((Component)window).GetComponentInChildren(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)OnExistingBarDrag); _boundContainer = val2; _boundMaxScroll = num; _boundContentX = val6.x; _boundRestY = val6.y; val7.OnDrag.AddListener((UnityAction)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 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 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() != (Object)null || (Object)(object)((Component)val2).GetComponent() != (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() == (Object)null && (Object)(object)((Component)viewport).GetComponent() == (Object)null) { ((Component)viewport).gameObject.AddComponent(); } } 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(); if ((Object)(object)component == (Object)null) { Image obj = ((Component)viewport).gameObject.AddComponent(); ((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(); if ((Object)(object)weaponSelectScrollDriver == (Object)null) { weaponSelectScrollDriver = ((Component)window).gameObject.AddComponent(); } 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 _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(); if ((Object)(object)weaponSelectScrollViewportProxy == (Object)null) { weaponSelectScrollViewportProxy = ((Component)_viewport).gameObject.AddComponent(); } 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() * 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(); 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) { } } }