using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.Movement;
using Sparroh.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("LoadoutImprovements")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LoadoutImprovements")]
[assembly: AssemblyTitle("LoadoutImprovements")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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;
}
}
}
public static class LoadoutExpanderMod
{
public static int PageOffset;
internal static FieldInfo _loadoutButtonsField;
internal static FieldInfo _upgradableField;
internal static MethodInfo _updateIconMethod;
public static Key ScrollLeftKey;
public static Key ScrollRightKey;
public static void TogglePage()
{
PageOffset += 3;
if (PageOffset > 6)
{
PageOffset = 0;
}
_ = PageOffset / 3;
RefreshCurrentWindow();
}
public static void ScrollRight()
{
PageOffset += 3;
if (PageOffset > 6)
{
PageOffset = 0;
}
RefreshCurrentWindow();
}
public static void ScrollLeft()
{
PageOffset -= 3;
if (PageOffset < 0)
{
PageOffset = 6;
}
RefreshCurrentWindow();
}
public static void RefreshCurrentWindow()
{
try
{
GearDetailsWindow[] array = Resources.FindObjectsOfTypeAll<GearDetailsWindow>();
foreach (GearDetailsWindow val in array)
{
if (((Component)val).gameObject.activeInHierarchy && _loadoutButtonsField != null && _updateIconMethod != null && _loadoutButtonsField.GetValue(val) is Array array2)
{
int num = Mathf.Min(array2.Length, 3);
for (int j = 0; j < num; j++)
{
object value = array2.GetValue(j);
_updateIconMethod.Invoke(val, new object[2] { value, j });
}
}
}
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Error refreshing window: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "UpdateLoadoutIcon")]
public static class UpdateIconPatch
{
[HarmonyPrefix]
public static void Prefix(ref int index)
{
if (index < 3)
{
index += LoadoutExpanderMod.PageOffset;
}
}
}
[HarmonyPatch(typeof(GearData), "EquipLoadout")]
public static class EquipLoadoutPatch
{
[HarmonyPrefix]
public static void Prefix(ref int index)
{
if (index < 3)
{
index += LoadoutExpanderMod.PageOffset;
}
}
}
[HarmonyPatch(typeof(GearData), "IncrementLoadoutIcon")]
public static class IncrementIconPatch
{
[HarmonyPrefix]
public static void Prefix(ref int index)
{
if (index < 3)
{
index += LoadoutExpanderMod.PageOffset;
}
}
}
[HarmonyPatch(typeof(GearData), "SaveLoadout")]
public static class SaveLoadoutPatch
{
[HarmonyPrefix]
public static void Prefix(ref int index)
{
if (index < 3)
{
index += LoadoutExpanderMod.PageOffset;
}
}
}
[HarmonyPatch]
public static class RenameGetPatch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("LoadoutHoverInfoPatches"), "GetLoadoutName", (Type[])null, (Type[])null);
}
private static void Prefix(ref int __1)
{
if (__1 < 3)
{
__1 += LoadoutExpanderMod.PageOffset;
}
}
}
[HarmonyPatch]
public static class RenameSetPatch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("LoadoutHoverInfoPatches"), "SetLoadoutName", (Type[])null, (Type[])null);
}
private static void Prefix(ref int __1)
{
if (__1 < 3)
{
__1 += LoadoutExpanderMod.PageOffset;
}
}
}
[HarmonyPatch(typeof(LoadoutHoverInfo), "GetTitle")]
public static class TooltipPatch
{
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void Postfix(LoadoutHoverInfo __instance, ref string title)
{
if (LoadoutExpanderMod.PageOffset == 0)
{
return;
}
try
{
GearDetailsWindow componentInParent = ((Component)__instance).GetComponentInParent<GearDetailsWindow>();
if ((Object)(object)componentInParent == (Object)null)
{
return;
}
int num = -1;
if (LoadoutExpanderMod._loadoutButtonsField.GetValue(componentInParent) is Array array)
{
for (int i = 0; i < array.Length; i++)
{
if (array.GetValue(i) == __instance)
{
num = i;
break;
}
}
}
if (num == -1 || num >= 3)
{
return;
}
int num2 = num + LoadoutExpanderMod.PageOffset;
string text = null;
object? obj = ((object)componentInParent).GetType().GetField("upgradable", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(componentInParent);
IUpgradable val = (IUpgradable)((obj is IUpgradable) ? obj : null);
if (val != null)
{
Type? typeFromHandle = typeof(PlayerData);
object obj2 = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
object obj3 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj2, new object[1] { val });
if (obj3 != null)
{
object? obj4 = obj3.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj3);
IUpgradable val2 = (IUpgradable)((obj4 is IUpgradable) ? obj4 : null);
if (val2 != null)
{
string text2 = $"{val2.Info.ID}_{num2}";
text = PlayerPrefs.GetString("LoadoutName_" + text2, "");
}
}
}
if (!string.IsNullOrEmpty(text))
{
title = text;
}
else
{
title = $"Loadout {num2 + 1}";
}
}
catch
{
}
}
}
[HarmonyPatch]
public static class LoadoutHighlightMod
{
private readonly struct EquipKey : IComparable<EquipKey>, IEquatable<EquipKey>
{
public readonly int UpgradeId;
public readonly sbyte X;
public readonly sbyte Y;
public readonly byte Rotation;
public EquipKey(int upgradeId, sbyte x, sbyte y, byte rotation)
{
UpgradeId = upgradeId;
X = x;
Y = y;
Rotation = rotation;
}
public int CompareTo(EquipKey other)
{
int upgradeId = UpgradeId;
int num = upgradeId.CompareTo(other.UpgradeId);
if (num != 0)
{
return num;
}
sbyte x = X;
num = x.CompareTo(other.X);
if (num != 0)
{
return num;
}
x = Y;
num = x.CompareTo(other.Y);
if (num != 0)
{
return num;
}
byte rotation = Rotation;
return rotation.CompareTo(other.Rotation);
}
public bool Equals(EquipKey other)
{
if (UpgradeId == other.UpgradeId && X == other.X && Y == other.Y)
{
return Rotation == other.Rotation;
}
return false;
}
public override bool Equals(object obj)
{
if (obj is EquipKey other)
{
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
return (((((UpgradeId * 397) ^ X) * 397) ^ Y) * 397) ^ Rotation;
}
}
private static readonly Color MatchedIconColor = Color.black;
private static readonly Color DefaultIconColor = Color.white;
private static readonly FieldInfo LoadoutsField = AccessTools.Field(typeof(GearData), "loadouts");
private static readonly FieldInfo EquippedUpgradesField = AccessTools.Field(typeof(GearData), "equippedUpgrades");
private static readonly Type LoadoutType = typeof(PlayerData).GetNestedType("Loadout", BindingFlags.NonPublic);
private static readonly FieldInfo LoadoutUpgradesField = LoadoutType?.GetField("upgrades", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly Dictionary<int, Color> OriginalIconColors = new Dictionary<int, Color>();
private static readonly Dictionary<int, Color> OriginalFillColors = new Dictionary<int, Color>();
private static readonly bool[] CachedMatch = new bool[3];
private static GearDetailsWindow CachedWindow;
private static int CachedPageOffset = int.MinValue;
private static int CachedEquippedHash;
private static int CachedLoadoutHash;
[HarmonyPatch(typeof(GearDetailsWindow), "UpdateLoadoutIcon")]
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void UpdateLoadoutIconPostfix(GearDetailsWindow __instance, LoadoutHoverInfo button, int index)
{
try
{
InvalidateCache();
ApplyHighlight(__instance, button, index);
}
catch (Exception ex)
{
ManualLogSource logger = SparrohPlugin.Logger;
if (logger != null)
{
logger.LogError((object)("LoadoutHighlight UpdateLoadoutIcon failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "Setup")]
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void SetupPostfix(GearDetailsWindow __instance)
{
try
{
InvalidateCache();
RefreshAll(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = SparrohPlugin.Logger;
if (logger != null)
{
logger.LogError((object)("LoadoutHighlight Setup failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "SetupUpgrades")]
[HarmonyPostfix]
public static void SetupUpgradesPostfix(GearDetailsWindow __instance)
{
try
{
InvalidateCache();
RefreshAll(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = SparrohPlugin.Logger;
if (logger != null)
{
logger.LogError((object)("LoadoutHighlight SetupUpgrades failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "EquipLoadout")]
[HarmonyPostfix]
public static void EquipLoadoutPostfix(GearDetailsWindow __instance)
{
try
{
InvalidateCache();
RefreshAll(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = SparrohPlugin.Logger;
if (logger != null)
{
logger.LogError((object)("LoadoutHighlight EquipLoadout failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "SaveLoadout")]
[HarmonyPostfix]
public static void SaveLoadoutPostfix(GearDetailsWindow __instance)
{
try
{
InvalidateCache();
RefreshAll(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = SparrohPlugin.Logger;
if (logger != null)
{
logger.LogError((object)("LoadoutHighlight SaveLoadout failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "Update")]
[HarmonyPostfix]
[HarmonyPriority(0)]
public static void UpdatePostfix(GearDetailsWindow __instance)
{
try
{
if (!((Object)(object)__instance == (Object)null) && ((Component)__instance).gameObject.activeInHierarchy)
{
EnsureMatchCache(__instance);
ApplyCachedColors(__instance);
}
}
catch (Exception ex)
{
ManualLogSource logger = SparrohPlugin.Logger;
if (logger != null)
{
logger.LogError((object)("LoadoutHighlight Update failed: " + ex.Message));
}
}
}
private static void InvalidateCache()
{
CachedWindow = null;
CachedPageOffset = int.MinValue;
CachedEquippedHash = 0;
CachedLoadoutHash = 0;
for (int i = 0; i < CachedMatch.Length; i++)
{
CachedMatch[i] = false;
}
}
public static void RefreshAll(GearDetailsWindow window)
{
if (!((Object)(object)window == (Object)null))
{
EnsureMatchCache(window);
ApplyCachedColors(window);
}
}
private static void EnsureMatchCache(GearDetailsWindow window)
{
int pageOffset = LoadoutExpanderMod.PageOffset;
int num = 0;
int num2 = 0;
try
{
IUpgradable upgradablePrefab = window.UpgradablePrefab;
if (upgradablePrefab != null)
{
GearData gearData = PlayerData.GetGearData(upgradablePrefab);
num = ComputeEquippedHash(gearData);
num2 = ComputeLoadoutsHash(gearData);
}
}
catch
{
}
if (!((Object)(object)CachedWindow != (Object)(object)window) && CachedPageOffset == pageOffset && CachedEquippedHash == num && CachedLoadoutHash == num2)
{
return;
}
CachedWindow = window;
CachedPageOffset = pageOffset;
CachedEquippedHash = num;
CachedLoadoutHash = num2;
Array loadoutButtons = GetLoadoutButtons(window);
if (loadoutButtons == null)
{
for (int i = 0; i < CachedMatch.Length; i++)
{
CachedMatch[i] = false;
}
return;
}
IUpgradable upgradablePrefab2 = window.UpgradablePrefab;
GearData gearData2 = ((upgradablePrefab2 != null) ? PlayerData.GetGearData(upgradablePrefab2) : null);
int num3 = Mathf.Min(loadoutButtons.Length, 3);
for (int j = 0; j < CachedMatch.Length; j++)
{
if (j < num3 && loadoutButtons.GetValue(j) is LoadoutHoverInfo)
{
int loadoutIndex = j + pageOffset;
CachedMatch[j] = LoadoutMatchesEquipped(gearData2, loadoutIndex);
}
else
{
CachedMatch[j] = false;
}
}
}
private static void ApplyCachedColors(GearDetailsWindow window)
{
//IL_000b: 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_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
Array loadoutButtons = GetLoadoutButtons(window);
if (loadoutButtons == null)
{
return;
}
Color playerUIColor = GetPlayerUIColor();
int num = Mathf.Min(loadoutButtons.Length, 3);
for (int i = 0; i < num; i++)
{
object? value = loadoutButtons.GetValue(i);
LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null);
if (val == null || (Object)(object)val == (Object)null)
{
continue;
}
Image iconImage = GetIconImage(val);
Graphic fillGraphic = GetFillGraphic(val, iconImage);
bool flag = CachedMatch[i];
if ((Object)(object)iconImage != (Object)null && ((Component)iconImage).gameObject.activeSelf)
{
int instanceID = ((Object)iconImage).GetInstanceID();
if (!OriginalIconColors.ContainsKey(instanceID))
{
Color color = ((Graphic)iconImage).color;
OriginalIconColors[instanceID] = (IsMatchedIconColor(color) ? DefaultIconColor : ((color.a > 0f) ? color : DefaultIconColor));
}
Color val2 = (flag ? MatchedIconColor : OriginalIconColors[instanceID]);
if (!ColorsApproximatelyEqual(((Graphic)iconImage).color, val2))
{
((Graphic)iconImage).color = val2;
}
}
if ((Object)(object)fillGraphic != (Object)null)
{
int instanceID2 = ((Object)fillGraphic).GetInstanceID();
if (!OriginalFillColors.ContainsKey(instanceID2))
{
Color color2 = fillGraphic.color;
OriginalFillColors[instanceID2] = (IsLikelyHighlightFill(color2, playerUIColor) ? Color.white : ((color2.a > 0f) ? color2 : Color.white));
}
Color val3 = (flag ? playerUIColor : OriginalFillColors[instanceID2]);
if (flag)
{
Color val4 = OriginalFillColors[instanceID2];
((Color)(ref val3))..ctor(playerUIColor.r, playerUIColor.g, playerUIColor.b, (val4.a > 0f) ? val4.a : 1f);
}
if (!ColorsApproximatelyEqual(fillGraphic.color, val3))
{
fillGraphic.color = val3;
}
}
}
}
private static void ApplyHighlight(GearDetailsWindow window, LoadoutHoverInfo button, int realIndex)
{
if (!((Object)(object)button == (Object)null) && !((Object)(object)window == (Object)null))
{
EnsureMatchCache(window);
ApplyCachedColors(window);
}
}
private static Array GetLoadoutButtons(GearDetailsWindow window)
{
Array array = null;
if (LoadoutExpanderMod._loadoutButtonsField != null)
{
array = LoadoutExpanderMod._loadoutButtonsField.GetValue(window) as Array;
}
if (array == null)
{
array = AccessTools.Field(typeof(GearDetailsWindow), "loadoutButtons")?.GetValue(window) as Array;
}
return array;
}
private static Image GetIconImage(LoadoutHoverInfo button)
{
Transform transform = ((Component)button).transform;
if (transform.childCount > 1)
{
Image component = ((Component)transform.GetChild(1)).GetComponent<Image>();
if ((Object)(object)component != (Object)null)
{
return component;
}
}
Image[] componentsInChildren = ((Component)button).GetComponentsInChildren<Image>(true);
if (componentsInChildren != null && componentsInChildren.Length > 1)
{
return componentsInChildren[1];
}
if (componentsInChildren != null && componentsInChildren.Length == 1)
{
return componentsInChildren[0];
}
return null;
}
private static Graphic GetFillGraphic(LoadoutHoverInfo button, Image icon)
{
if ((Object)(object)button == (Object)null)
{
return null;
}
Transform transform = ((Component)button).transform;
if (transform.childCount > 0)
{
Graphic component = ((Component)transform.GetChild(0)).GetComponent<Graphic>();
if ((Object)(object)component != (Object)null && (Object)(object)component != (Object)(object)icon)
{
return component;
}
}
Graphic component2 = ((Component)button).GetComponent<Graphic>();
if ((Object)(object)component2 != (Object)null && (Object)(object)component2 != (Object)(object)icon)
{
return component2;
}
Image[] componentsInChildren = ((Component)button).GetComponentsInChildren<Image>(true);
if (componentsInChildren != null)
{
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null && (Object)(object)componentsInChildren[i] != (Object)(object)icon)
{
return (Graphic)(object)componentsInChildren[i];
}
}
}
return null;
}
private static Color GetPlayerUIColor()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: 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_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
try
{
return Global.UIColor;
}
catch
{
return Color.white;
}
}
private static bool IsMatchedIconColor(Color c)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return ColorsApproximatelyEqual(c, MatchedIconColor);
}
private static bool IsLikelyHighlightFill(Color current, Color uiColor)
{
//IL_0000: 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_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if (Mathf.Abs(current.r - uiColor.r) < 0.01f && Mathf.Abs(current.g - uiColor.g) < 0.01f)
{
return Mathf.Abs(current.b - uiColor.b) < 0.01f;
}
return false;
}
private static bool ColorsApproximatelyEqual(Color a, Color b)
{
//IL_0000: 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_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
if (Mathf.Abs(a.r - b.r) < 0.01f && Mathf.Abs(a.g - b.g) < 0.01f && Mathf.Abs(a.b - b.b) < 0.01f)
{
return Mathf.Abs(a.a - b.a) < 0.01f;
}
return false;
}
private static int ComputeEquippedHash(GearData gearData)
{
if (gearData == null || EquippedUpgradesField == null)
{
return 0;
}
if (!(EquippedUpgradesField.GetValue(gearData) is IList { Count: not 0 } list))
{
return 0;
}
int num = 17;
num = num * 31 + list.Count;
List<EquipKey> list2 = ToSortedKeys(list);
for (int i = 0; i < list2.Count; i++)
{
num = num * 31 + list2[i].GetHashCode();
}
return num;
}
private static int ComputeLoadoutsHash(GearData gearData)
{
if (gearData == null || LoadoutsField == null || LoadoutUpgradesField == null)
{
return 0;
}
if (!(LoadoutsField.GetValue(gearData) is Array array))
{
return 0;
}
int num = 17;
num = num * 31 + array.Length;
int num2 = Mathf.Min(array.Length, 9);
for (int i = 0; i < num2; i++)
{
object value = array.GetValue(i);
if (value == null)
{
num *= 31;
continue;
}
if (!(LoadoutUpgradesField.GetValue(value) is IList list))
{
num *= 31;
continue;
}
num = num * 31 + list.Count;
List<EquipKey> list2 = ToSortedKeys(list);
for (int j = 0; j < list2.Count; j++)
{
num = num * 31 + list2[j].GetHashCode();
}
}
return num;
}
private static bool LoadoutMatchesEquipped(GearData gearData, int loadoutIndex)
{
if (gearData == null || LoadoutsField == null || EquippedUpgradesField == null || LoadoutUpgradesField == null)
{
return false;
}
if (!(EquippedUpgradesField.GetValue(gearData) is IList { Count: not 0 } list))
{
return false;
}
if (!(LoadoutsField.GetValue(gearData) is Array array) || loadoutIndex < 0 || loadoutIndex >= array.Length)
{
return false;
}
object value = array.GetValue(loadoutIndex);
if (value == null)
{
return false;
}
if (!(LoadoutUpgradesField.GetValue(value) is IList { Count: not 0 } list2))
{
return false;
}
if (list2.Count != list.Count)
{
return false;
}
List<EquipKey> list3 = ToSortedKeys(list);
List<EquipKey> list4 = ToSortedKeys(list2);
if (list3.Count != list4.Count || list3.Count == 0)
{
return false;
}
for (int i = 0; i < list3.Count; i++)
{
if (!list3[i].Equals(list4[i]))
{
return false;
}
}
return true;
}
private static List<EquipKey> ToSortedKeys(IList list)
{
//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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: 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)
List<EquipKey> list2 = new List<EquipKey>(list.Count);
for (int i = 0; i < list.Count; i++)
{
object obj = list[i];
if (obj == null)
{
continue;
}
if (obj is UpgradeEquipData val)
{
list2.Add(new EquipKey(val.upgradeID, val.x, val.y, val.rotation));
continue;
}
try
{
Type type = obj.GetType();
int upgradeId = Convert.ToInt32(AccessTools.Field(type, "upgradeID")?.GetValue(obj) ?? ((object)0));
sbyte x = Convert.ToSByte(AccessTools.Field(type, "x")?.GetValue(obj) ?? ((object)(sbyte)0));
sbyte y = Convert.ToSByte(AccessTools.Field(type, "y")?.GetValue(obj) ?? ((object)(sbyte)0));
byte rotation = Convert.ToByte(AccessTools.Field(type, "rotation")?.GetValue(obj) ?? ((object)(byte)0));
list2.Add(new EquipKey(upgradeId, x, y, rotation));
}
catch
{
}
}
list2.Sort();
return list2;
}
}
[HarmonyPatch]
public static class LoadoutPreviewMod
{
public class UpgradePlacement
{
public UpgradeInstance Upgrade;
public int X;
public int Y;
public byte Rotation;
}
private static MonoBehaviour currentPreview;
private static int lastHoveredIndex = -1;
private static string currentPreviewType = null;
private static int yOffset = 0;
internal static ConfigEntry<bool> enableTextMode;
internal static string CurrentPreviewMode;
public static void ApplyPatches(Harmony harmony)
{
try
{
Patch(harmony);
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Failed to apply LoadoutPreviewMod patches: " + ex.Message));
}
}
public static void OnConfigChanged()
{
try
{
UpdatePreviewMode();
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Error in LoadoutPreviewMod.OnConfigChanged: " + ex.Message));
}
}
public static void UpdatePreviewMode()
{
try
{
if (enableTextMode.Value)
{
CurrentPreviewMode = "text";
}
else
{
CurrentPreviewMode = "disabled";
}
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Error in LoadoutPreviewMod.UpdatePreviewMode: " + ex.Message));
}
}
public static void Destroy()
{
try
{
if ((Object)(object)currentPreview != (Object)null)
{
((TextPreview)(object)currentPreview).Hide();
currentPreview = null;
}
currentPreviewType = null;
lastHoveredIndex = -1;
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Error destroying LoadoutPreviewMod: " + ex.Message));
}
}
public static void Patch(Harmony harmony)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
harmony.Patch((MethodBase)AccessTools.Method(typeof(GearDetailsWindow), "OnOpen", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LoadoutPreviewMod), "OnOpenPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)AccessTools.Method(typeof(GearDetailsWindow), "OnCloseCallback", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LoadoutPreviewMod), "OnCloseCallbackPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)AccessTools.Method(typeof(GearDetailsWindow), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LoadoutPreviewMod), "UpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
[HarmonyPatch(typeof(GearDetailsWindow), "OnOpen")]
[HarmonyPostfix]
public static void OnOpenPostfix(GearDetailsWindow __instance)
{
if (CurrentPreviewMode == "disabled")
{
currentPreview = null;
currentPreviewType = "disabled";
lastHoveredIndex = -1;
}
else
{
currentPreview = (MonoBehaviour)(object)CreateTextPreview(__instance);
currentPreviewType = CurrentPreviewMode;
lastHoveredIndex = -1;
}
}
private static TextPreview CreateTextPreview(GearDetailsWindow window)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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_0033: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("TextPreview");
val.transform.SetParent(((Component)window).transform, false);
TextPreview result = val.AddComponent<TextPreview>();
val.GetComponent<RectTransform>().anchoredPosition = new Vector2(10000f, 10000f);
val.SetActive(false);
return result;
}
[HarmonyPatch(typeof(GearDetailsWindow), "OnCloseCallback")]
[HarmonyPostfix]
public static void OnCloseCallbackPostfix()
{
if ((Object)(object)currentPreview != (Object)null)
{
((TextPreview)(object)currentPreview).Hide();
}
currentPreviewType = null;
lastHoveredIndex = -1;
}
[HarmonyPatch(typeof(GearDetailsWindow), "Update")]
[HarmonyPostfix]
public static void UpdatePostfix(GearDetailsWindow __instance)
{
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: 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_009f: 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_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
if (currentPreviewType != CurrentPreviewMode)
{
if ((Object)(object)currentPreview != (Object)null)
{
((TextPreview)(object)currentPreview).Hide();
currentPreview = null;
}
if (CurrentPreviewMode == "text")
{
currentPreview = (MonoBehaviour)(object)CreateTextPreview(__instance);
}
currentPreviewType = CurrentPreviewMode;
}
if ((Object)(object)currentPreview == (Object)null || !(Traverse.Create((object)__instance).Field("loadoutButtons").GetValue() is LoadoutHoverInfo[] array))
{
return;
}
int num = -1;
MenuActions menu = PlayerInput.Controls.Menu;
Vector2 mousePos = ((MenuActions)(ref menu)).Point.ReadValue<Vector2>();
for (int i = 0; i < array.Length; i++)
{
if ((Object)(object)array[i] != (Object)null && IsButtonHovered(array[i], mousePos))
{
num = i;
break;
}
}
if (num == lastHoveredIndex)
{
return;
}
if (lastHoveredIndex >= 0)
{
((TextPreview)(object)currentPreview).Hide();
}
if (num >= 0)
{
List<UpgradePlacement> loadoutUpgradePlacements = GetLoadoutUpgradePlacements(__instance, num);
if (loadoutUpgradePlacements.Count > 0)
{
int num2 = loadoutUpgradePlacements.Min((UpgradePlacement p) => p.Y);
if (num2 < 0)
{
foreach (UpgradePlacement item in loadoutUpgradePlacements)
{
item.Y -= num2;
}
}
Vector2 position = CalculatePreviewPosition(mousePos);
((TextPreview)(object)currentPreview).Setup(loadoutUpgradePlacements);
((TextPreview)(object)currentPreview).SetPosition(position);
((TextPreview)(object)currentPreview).Show();
}
}
lastHoveredIndex = num;
}
private static bool IsButtonHovered(LoadoutHoverInfo button, Vector2 mousePos)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
PointerEventData val = new PointerEventData(EventSystem.current)
{
position = mousePos
};
List<RaycastResult> list = new List<RaycastResult>();
EventSystem.current.RaycastAll(val, list);
return list.Any((RaycastResult r) => (Object)(object)((RaycastResult)(ref r)).gameObject == (Object)(object)((Component)button).gameObject);
}
private static Vector2 CalculatePreviewPosition(Vector2 mousePos)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_002a: 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_003a: 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_0040: Unknown result type (might be due to invalid IL or missing references)
Canvas componentInParent = ((Component)Menu.Instance).gameObject.GetComponentInParent<Canvas>();
Vector2 val = default(Vector2);
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Component)componentInParent).transform, mousePos, componentInParent.worldCamera, ref val);
return val + new Vector2(500f, -250f);
}
private static List<UpgradePlacement> GetLoadoutUpgradePlacements(GearDetailsWindow window, int loadoutIndex)
{
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Expected O, but got Unknown
List<UpgradePlacement> list = new List<UpgradePlacement>();
try
{
object value = Traverse.Create((object)window).Property("UpgradablePrefab", (object[])null).GetValue();
if (value == null)
{
return list;
}
object value2 = typeof(PlayerData).GetProperty("Instance").GetValue(null);
object obj = typeof(PlayerData).GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(value2, new object[1] { value });
if (obj == null)
{
return list;
}
Array array = (Array)(obj.GetType().GetField("loadouts", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj));
if (array == null || loadoutIndex < 0 || loadoutIndex >= array.Length)
{
return list;
}
object value3 = array.GetValue(loadoutIndex);
if (value3 == null)
{
return list;
}
object value4 = Traverse.Create(value3).Field("upgrades").GetValue();
if (value4 == null)
{
return list;
}
if (!(value4 is IList list2))
{
return list;
}
for (int i = 0; i < list2.Count; i++)
{
object obj2 = list2[i];
if (obj2 != null)
{
UpgradeInstance val = (UpgradeInstance)Traverse.Create(obj2).Method("GetUpgrade", Array.Empty<object>()).GetValue();
if (val != null)
{
UpgradePlacement upgradePlacement = new UpgradePlacement();
sbyte x = (sbyte)Traverse.Create(obj2).Field("x").GetValue();
sbyte b = (sbyte)Traverse.Create(obj2).Field("y").GetValue();
upgradePlacement.X = x;
upgradePlacement.Y = b - yOffset;
upgradePlacement.Rotation = (byte)Traverse.Create(obj2).Field("rotation").GetValue();
upgradePlacement.Upgrade = val;
list.Add(upgradePlacement);
}
}
}
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Error getting loadout placements: " + ex.Message));
}
return list;
}
}
[HarmonyPatch]
public static class PlayerDataPatches
{
private const int MAX_LOADOUT_SLOTS = 9;
private static readonly Type LoadoutType = typeof(PlayerData).GetNestedType("Loadout", BindingFlags.NonPublic);
private static readonly Type UpgradeEquipDataType = typeof(UpgradeEquipData);
private static readonly FieldInfo LoadoutUpgradesField = LoadoutType?.GetField("upgrades", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo LoadoutIconIndexField = LoadoutType?.GetField("iconIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
[HarmonyPatch(typeof(GearData), "SaveLoadout")]
[HarmonyPrefix]
public static bool SaveLoadoutPrefix(ref GearData __instance, int index, ref object ___loadouts)
{
Array array = ___loadouts as Array;
if (array == null)
{
array = (Array)(___loadouts = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9)));
}
if (index >= array.Length)
{
Array array2 = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9));
array.CopyTo(array2, 0);
___loadouts = array2;
}
return true;
}
[HarmonyPatch(typeof(GearData), "EquipLoadout")]
[HarmonyPrefix]
public static bool EquipLoadoutPrefix(ref GearData __instance, int index, ref object ___loadouts, ref bool __result)
{
Array array = ___loadouts as Array;
if (array == null)
{
array = (Array)(___loadouts = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9)));
}
if (index >= array.Length)
{
Array array2 = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9));
array.CopyTo(array2, 0);
___loadouts = array2;
}
if (index < 0 || index >= array.Length)
{
__result = false;
return false;
}
return true;
}
[HarmonyPatch(typeof(GearData), "IncrementLoadoutIcon")]
[HarmonyPrefix]
[HarmonyPriority(0)]
public static bool IncrementLoadoutIconPrefix(int index, ref object ___loadouts, ref bool __result)
{
try
{
if (LoadoutType == null || LoadoutIconIndexField == null)
{
SparrohPlugin.Logger.LogError((object)"IncrementLoadoutIcon: Loadout type/fields not resolved.");
__result = false;
return false;
}
Array array = ___loadouts as Array;
if (array == null)
{
array = (Array)(___loadouts = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9)));
}
if (index < 0)
{
__result = false;
return false;
}
if (index >= array.Length)
{
Array array2 = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9));
array.CopyTo(array2, 0);
___loadouts = array2;
array = array2;
}
object value = array.GetValue(index);
IList list = LoadoutUpgradesField?.GetValue(value) as IList;
if (list == null)
{
list = Activator.CreateInstance(typeof(List<>).MakeGenericType(UpgradeEquipDataType), 8) as IList;
LoadoutUpgradesField?.SetValue(value, list);
}
int count = list.Count;
int num = (((Object)(object)Global.Instance != (Object)null && Global.Instance.LoadoutIcons != null) ? Global.Instance.LoadoutIcons.Length : 0);
int num2 = Mathf.Max(1, count + num);
int num3 = (((LoadoutIconIndexField.GetValue(value) is int num4) ? num4 : 0) + 1) % num2;
LoadoutIconIndexField.SetValue(value, num3);
array.SetValue(value, index);
__result = true;
return false;
}
catch (Exception arg)
{
SparrohPlugin.Logger.LogError((object)$"IncrementLoadoutIcon failed: {arg}");
__result = false;
return false;
}
}
[HarmonyPatch(typeof(GearData), "GetLoadoutIcon")]
[HarmonyPostfix]
public static void GetLoadoutIconPostfix(int index, ref object ___loadouts, ref Sprite __result)
{
try
{
if (LoadoutType == null || LoadoutUpgradesField == null || LoadoutIconIndexField == null || !(___loadouts is Array array) || index < 0 || index >= array.Length)
{
return;
}
object value = array.GetValue(index);
if (!(LoadoutUpgradesField.GetValue(value) is IList { Count: not 0, Count: var count } list))
{
return;
}
int num = ((LoadoutIconIndexField.GetValue(value) is int num2) ? num2 : 0);
if (num < count)
{
Sprite upgradeIconFromEquipData = GetUpgradeIconFromEquipData(list[num]);
if ((Object)(object)upgradeIconFromEquipData != (Object)null)
{
__result = upgradeIconFromEquipData;
return;
}
}
if (Global.Instance?.LoadoutIcons != null)
{
int num3 = num - count;
if (num3 < 0)
{
num3 = 0;
}
Sprite[] loadoutIcons = Global.Instance.LoadoutIcons;
if (num3 >= 0 && num3 < loadoutIcons.Length)
{
__result = loadoutIcons[num3];
}
else if (loadoutIcons.Length != 0)
{
__result = loadoutIcons[Mathf.Min(num, loadoutIcons.Length - 1)];
}
}
}
catch (Exception arg)
{
SparrohPlugin.Logger.LogError((object)$"GetLoadoutIcon postfix failed: {arg}");
}
}
private static Sprite GetUpgradeIconFromEquipData(object equipData)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (equipData == null)
{
return null;
}
try
{
if (equipData is UpgradeEquipData val)
{
UpgradeInstance upgrade = ((UpgradeEquipData)(ref val)).GetUpgrade();
object result;
if (upgrade == null)
{
result = null;
}
else
{
Upgrade upgrade2 = upgrade.Upgrade;
result = ((upgrade2 != null) ? upgrade2.Icon : null);
}
return (Sprite)result;
}
object? obj = (UpgradeEquipDataType?.GetMethod("GetUpgrade", BindingFlags.Instance | BindingFlags.Public))?.Invoke(equipData, null);
object? obj2 = ((obj is UpgradeInstance) ? obj : null);
object result2;
if (obj2 == null)
{
result2 = null;
}
else
{
Upgrade upgrade3 = ((UpgradeInstance)obj2).Upgrade;
result2 = ((upgrade3 != null) ? upgrade3.Icon : null);
}
return (Sprite)result2;
}
catch (Exception ex)
{
SparrohPlugin.Logger.LogError((object)("Failed to resolve upgrade icon: " + ex.Message));
return null;
}
}
}
[HarmonyPatch]
public static class GearDetailsWindowPatches
{
private const int NEW_LOADOUT_COUNT = 9;
private static FieldInfo loadoutButtonsField;
[HarmonyPatch(typeof(GearDetailsWindow), "Setup")]
[HarmonyPostfix]
public static void SetupPostfix(ref GearDetailsWindow __instance, IUpgradable upgradable)
{
LoadoutExpanderMod.PageOffset = 0;
LoadoutExpanderMod.RefreshCurrentWindow();
try
{
Type typeFromHandle = typeof(PlayerData);
object obj = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
object obj2 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj, new object[1] { upgradable });
if (obj2 != null)
{
FieldInfo field = obj2.GetType().GetField("loadouts", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
Array array = field.GetValue(obj2) as Array;
Type nestedType = typeFromHandle.GetNestedType("Loadout", BindingFlags.NonPublic);
if (array == null || array.Length < 9)
{
Array array2 = Array.CreateInstance(nestedType, 9);
array?.CopyTo(array2, 0);
field.SetValue(obj2, array2);
}
}
}
}
catch (Exception)
{
}
FieldInfo field2 = ((object)__instance).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic);
if (field2 != null && field2.GetValue(__instance) is Array { Length: var length } array3)
{
for (int i = 0; i < Mathf.Min(9, length); i++)
{
object value = array3.GetValue(i);
if (value != null)
{
object obj3 = value.GetType().GetProperty("gameObject")?.GetValue(value);
obj3?.GetType().GetMethod("SetActive")?.Invoke(obj3, new object[1] { true });
}
}
_ = 9;
}
try
{
if (upgradable == null)
{
return;
}
Type? typeFromHandle2 = typeof(PlayerData);
object obj4 = typeFromHandle2.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
object obj5 = typeFromHandle2.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj4, new object[1] { upgradable });
if (obj5 == null)
{
return;
}
object? obj6 = obj5.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj5);
IUpgradable val = (IUpgradable)((obj6 is IUpgradable) ? obj6 : null);
if (val == null)
{
return;
}
if (!LoadoutHoverInfoPatches.windowLoadoutNames.TryGetValue(__instance, out var value2))
{
value2 = new Dictionary<int, string>();
LoadoutHoverInfoPatches.windowLoadoutNames[__instance] = value2;
}
for (int j = 0; j < 9; j++)
{
string text = $"{val.Info.ID}_{j}";
string value3 = PlayerPrefs.GetString("LoadoutName_" + text, "");
if (!string.IsNullOrEmpty(value3))
{
value2[j] = value3;
}
}
}
catch (Exception)
{
}
}
private static void UpdateLoadoutIcon(GearDetailsWindow instance, LoadoutHoverInfo button, int index)
{
typeof(GearDetailsWindow).GetMethod("UpdateLoadoutIcon", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(instance, new object[2] { button, index });
}
}
[HarmonyPatch]
public static class LoadoutHoverInfoPatches
{
[HarmonyPatch]
public class LoadoutRenameDialog : MonoBehaviour
{
private static LoadoutRenameDialog Instance;
private Canvas canvas;
private Image background;
private TMP_InputField inputField;
private Button applyButton;
private Button cancelButton;
private TextMeshProUGUI applyText;
private TextMeshProUGUI cancelText;
private Action<string> onApplyCallback;
private Action onCancelCallback;
private GearDetailsWindow window;
private int loadoutIndex;
public static bool IsActive => (Object)(object)Instance != (Object)null;
public static void Show(Vector2 screenPosition, string currentName, Action<string> onApply, Action onCancel, GearDetailsWindow targetWindow, int targetLoadoutIndex)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
if (IsActive)
{
Close();
}
WindowSystem windowSystem = GameManager.Instance.WindowSystem;
GameObject val = new GameObject("LoadoutRenameDialog");
val.transform.SetParent(((Component)windowSystem).transform, false);
LoadoutRenameDialog loadoutRenameDialog = val.AddComponent<LoadoutRenameDialog>();
loadoutRenameDialog.Initialize(screenPosition, currentName, onApply, onCancel, targetWindow, targetLoadoutIndex);
Instance = loadoutRenameDialog;
}
public static void Close()
{
if ((Object)(object)Instance != (Object)null)
{
Object.Destroy((Object)(object)((Component)Instance).gameObject);
Instance = null;
}
}
private void Initialize(Vector2 screenPosition, string currentName, Action<string> onApply, Action onCancel, GearDetailsWindow targetWindow, int targetLoadoutIndex)
{
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Expected O, but got Unknown
//IL_0106: 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_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Expected O, but got Unknown
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_025c: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: 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)
//IL_028f: Unknown result type (might be due to invalid IL or missing references)
//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0317: Unknown result type (might be due to invalid IL or missing references)
//IL_033b: Unknown result type (might be due to invalid IL or missing references)
//IL_035f: Unknown result type (might be due to invalid IL or missing references)
//IL_0383: Unknown result type (might be due to invalid IL or missing references)
//IL_0392: Unknown result type (might be due to invalid IL or missing references)
//IL_0399: Expected O, but got Unknown
//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
//IL_041c: Unknown result type (might be due to invalid IL or missing references)
//IL_0440: Unknown result type (might be due to invalid IL or missing references)
//IL_0464: Unknown result type (might be due to invalid IL or missing references)
//IL_0488: Unknown result type (might be due to invalid IL or missing references)
//IL_0497: Unknown result type (might be due to invalid IL or missing references)
//IL_049e: Expected O, but got Unknown
//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
//IL_050f: Unknown result type (might be due to invalid IL or missing references)
//IL_0529: Unknown result type (might be due to invalid IL or missing references)
//IL_0543: Unknown result type (might be due to invalid IL or missing references)
//IL_0552: Unknown result type (might be due to invalid IL or missing references)
//IL_0559: Expected O, but got Unknown
//IL_0594: Unknown result type (might be due to invalid IL or missing references)
//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
//IL_0600: Unknown result type (might be due to invalid IL or missing references)
//IL_0624: Unknown result type (might be due to invalid IL or missing references)
//IL_0648: Unknown result type (might be due to invalid IL or missing references)
//IL_0657: Unknown result type (might be due to invalid IL or missing references)
//IL_065e: Expected O, but got Unknown
//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
//IL_06cf: Unknown result type (might be due to invalid IL or missing references)
//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0703: Unknown result type (might be due to invalid IL or missing references)
//IL_071f: Unknown result type (might be due to invalid IL or missing references)
//IL_0729: Expected O, but got Unknown
//IL_073b: Unknown result type (might be due to invalid IL or missing references)
//IL_0745: Expected O, but got Unknown
window = targetWindow;
loadoutIndex = targetLoadoutIndex;
onApplyCallback = onApply;
onCancelCallback = onCancel;
object? obj = ((object)window).GetType().GetProperty("gameObject")?.GetValue(window);
GameObject val = (GameObject)((obj is GameObject) ? obj : null);
if ((Object)(object)val != (Object)null)
{
canvas = val.GetComponentInParent<Canvas>();
}
if ((Object)(object)canvas == (Object)null)
{
canvas = Object.FindObjectOfType<Canvas>();
}
if (!((Object)(object)canvas == (Object)null))
{
((Component)this).transform.SetParent(((Component)canvas).transform, false);
CanvasGroup obj2 = ((Component)this).gameObject.AddComponent<CanvasGroup>();
obj2.alpha = 1f;
obj2.interactable = true;
obj2.blocksRaycasts = true;
GameObject val2 = new GameObject("Background");
val2.transform.SetParent(((Component)this).transform, false);
background = val2.AddComponent<Image>();
((Graphic)background).color = new Color(0.2f, 0.2f, 0.2f, 0.95f);
Transform transform = ((Component)background).transform;
((RectTransform)((transform is RectTransform) ? transform : null)).anchorMin = new Vector2(0.5f, 0.5f);
Transform transform2 = ((Component)background).transform;
((RectTransform)((transform2 is RectTransform) ? transform2 : null)).anchorMax = new Vector2(0.5f, 0.5f);
Transform transform3 = ((Component)background).transform;
((RectTransform)((transform3 is RectTransform) ? transform3 : null)).pivot = new Vector2(0.5f, 0.5f);
Transform transform4 = ((Component)background).transform;
((RectTransform)((transform4 is RectTransform) ? transform4 : null)).sizeDelta = new Vector2(300f, 120f);
Transform transform5 = ((Component)canvas).transform;
Vector2 val3 = default(Vector2);
RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)(object)((transform5 is RectTransform) ? transform5 : null), screenPosition, canvas.worldCamera, ref val3);
val3.x += 300f;
val3.y += 200f;
((Component)this).transform.localPosition = Vector2.op_Implicit(val3);
GameObject val4 = new GameObject("InputField");
val4.transform.SetParent(((Component)this).transform, false);
inputField = val4.AddComponent<TMP_InputField>();
GameObject val5 = new GameObject("Text");
val5.transform.SetParent(val4.transform, false);
TextMeshProUGUI val6 = val5.AddComponent<TextMeshProUGUI>();
inputField.textComponent = (TMP_Text)(object)val6;
((TMP_Text)val6).fontSize = 24f;
((Graphic)val6).color = Color.white;
((TMP_Text)val6).rectTransform.anchorMin = Vector2.zero;
((TMP_Text)val6).rectTransform.anchorMax = Vector2.one;
((TMP_Text)val6).rectTransform.sizeDelta = Vector2.zero;
inputField.text = currentName;
inputField.caretColor = Color.white;
((Graphic)val4.AddComponent<Image>()).color = new Color(0.1f, 0.1f, 0.1f, 1f);
Transform transform6 = ((Component)inputField).transform;
((RectTransform)((transform6 is RectTransform) ? transform6 : null)).anchorMin = new Vector2(0.5f, 0.5f);
Transform transform7 = ((Component)inputField).transform;
((RectTransform)((transform7 is RectTransform) ? transform7 : null)).anchorMax = new Vector2(0.5f, 0.5f);
Transform transform8 = ((Component)inputField).transform;
((RectTransform)((transform8 is RectTransform) ? transform8 : null)).pivot = new Vector2(0.5f, 0.5f);
Transform transform9 = ((Component)inputField).transform;
((RectTransform)((transform9 is RectTransform) ? transform9 : null)).sizeDelta = new Vector2(250f, 40f);
Transform transform10 = ((Component)inputField).transform;
((RectTransform)((transform10 is RectTransform) ? transform10 : null)).anchoredPosition = new Vector2(0f, 20f);
GameObject val7 = new GameObject("ApplyButton");
val7.transform.SetParent(((Component)this).transform, false);
applyButton = val7.AddComponent<Button>();
((Graphic)val7.AddComponent<Image>()).color = new Color(0.3f, 0.6f, 0.3f, 1f);
Transform transform11 = ((Component)applyButton).transform;
((RectTransform)((transform11 is RectTransform) ? transform11 : null)).anchorMin = new Vector2(0.5f, 0.5f);
Transform transform12 = ((Component)applyButton).transform;
((RectTransform)((transform12 is RectTransform) ? transform12 : null)).anchorMax = new Vector2(0.5f, 0.5f);
Transform transform13 = ((Component)applyButton).transform;
((RectTransform)((transform13 is RectTransform) ? transform13 : null)).pivot = new Vector2(0.5f, 0.5f);
Transform transform14 = ((Component)applyButton).transform;
((RectTransform)((transform14 is RectTransform) ? transform14 : null)).sizeDelta = new Vector2(80f, 35f);
Transform transform15 = ((Component)applyButton).transform;
((RectTransform)((transform15 is RectTransform) ? transform15 : null)).anchoredPosition = new Vector2(-50f, -35f);
GameObject val8 = new GameObject("ApplyText");
val8.transform.SetParent(val7.transform, false);
applyText = val8.AddComponent<TextMeshProUGUI>();
((TMP_Text)applyText).text = "Apply";
((TMP_Text)applyText).fontSize = 20f;
((Graphic)applyText).color = Color.white;
((TMP_Text)applyText).alignment = (TextAlignmentOptions)514;
Transform transform16 = ((TMP_Text)applyText).transform;
((RectTransform)((transform16 is RectTransform) ? transform16 : null)).anchorMin = Vector2.zero;
Transform transform17 = ((TMP_Text)applyText).transform;
((RectTransform)((transform17 is RectTransform) ? transform17 : null)).anchorMax = Vector2.one;
Transform transform18 = ((TMP_Text)applyText).transform;
((RectTransform)((transform18 is RectTransform) ? transform18 : null)).sizeDelta = Vector2.zero;
GameObject val9 = new GameObject("CancelButton");
val9.transform.SetParent(((Component)this).transform, false);
cancelButton = val9.AddComponent<Button>();
((Graphic)val9.AddComponent<Image>()).color = new Color(0.6f, 0.3f, 0.3f, 1f);
Transform transform19 = ((Component)cancelButton).transform;
((RectTransform)((transform19 is RectTransform) ? transform19 : null)).anchorMin = new Vector2(0.5f, 0.5f);
Transform transform20 = ((Component)cancelButton).transform;
((RectTransform)((transform20 is RectTransform) ? transform20 : null)).anchorMax = new Vector2(0.5f, 0.5f);
Transform transform21 = ((Component)cancelButton).transform;
((RectTransform)((transform21 is RectTransform) ? transform21 : null)).pivot = new Vector2(0.5f, 0.5f);
Transform transform22 = ((Component)cancelButton).transform;
((RectTransform)((transform22 is RectTransform) ? transform22 : null)).sizeDelta = new Vector2(80f, 35f);
Transform transform23 = ((Component)cancelButton).transform;
((RectTransform)((transform23 is RectTransform) ? transform23 : null)).anchoredPosition = new Vector2(50f, -35f);
GameObject val10 = new GameObject("CancelText");
val10.transform.SetParent(val9.transform, false);
cancelText = val10.AddComponent<TextMeshProUGUI>();
((TMP_Text)cancelText).text = "Cancel";
((TMP_Text)cancelText).fontSize = 20f;
((Graphic)cancelText).color = Color.white;
((TMP_Text)cancelText).alignment = (TextAlignmentOptions)514;
Transform transform24 = ((TMP_Text)cancelText).transform;
((RectTransform)((transform24 is RectTransform) ? transform24 : null)).anchorMin = Vector2.zero;
Transform transform25 = ((TMP_Text)cancelText).transform;
((RectTransform)((transform25 is RectTransform) ? transform25 : null)).anchorMax = Vector2.one;
Transform transform26 = ((TMP_Text)cancelText).transform;
((RectTransform)((transform26 is RectTransform) ? transform26 : null)).sizeDelta = Vector2.zero;
((UnityEvent)applyButton.onClick).AddListener(new UnityAction(OnApplyClicked));
((UnityEvent)cancelButton.onClick).AddListener(new UnityAction(OnCancelClicked));
inputField.ActivateInputField();
((Selectable)inputField).Select();
}
}
private void OnApplyClicked()
{
if (!string.IsNullOrWhiteSpace(inputField.text))
{
onApplyCallback?.Invoke(inputField.text);
}
Close();
}
private void OnCancelClicked()
{
onCancelCallback?.Invoke();
Close();
}
private void Update()
{
Keyboard current = Keyboard.current;
if (current != null)
{
if (((ButtonControl)current.enterKey).wasPressedThisFrame || ((ButtonControl)current.numpadEnterKey).wasPressedThisFrame)
{
OnApplyClicked();
}
else if (((ButtonControl)current.escapeKey).wasPressedThisFrame)
{
OnCancelClicked();
}
}
}
private void OnDestroy()
{
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
}
private static readonly Type LoadoutHoverInfoType = AccessTools.TypeByName("LoadoutHoverInfo");
private static bool isRenaming = false;
private static string currentRenameValue = "";
private static LoadoutHoverInfo currentlyRenamingButton = null;
private static readonly Dictionary<int, string> loadoutNames = new Dictionary<int, string>();
public static Key RenameKey = (Key)26;
internal static readonly Dictionary<GearDetailsWindow, Dictionary<int, string>> windowLoadoutNames = new Dictionary<GearDetailsWindow, Dictionary<int, string>>();
private static string GetLoadoutName(GearDetailsWindow window, int loadoutIndex)
{
try
{
if (windowLoadoutNames.TryGetValue(window, out var value) && value.TryGetValue(loadoutIndex, out var value2) && !string.IsNullOrEmpty(value2))
{
return value2;
}
object? obj = ((object)window).GetType().GetField("upgradable", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window);
IUpgradable val = (IUpgradable)((obj is IUpgradable) ? obj : null);
if (val != null)
{
Type? typeFromHandle = typeof(PlayerData);
object obj2 = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
object obj3 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj2, new object[1] { val });
if (obj3 != null)
{
object? obj4 = obj3.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj3);
IUpgradable val2 = (IUpgradable)((obj4 is IUpgradable) ? obj4 : null);
if (val2 != null)
{
string text = $"{val2.Info.ID}_{loadoutIndex}";
string text2 = PlayerPrefs.GetString("LoadoutName_" + text, "");
SparrohPlugin.Logger.LogInfo((object)$"Retrieving name for gear {val2.Info.ID} slot {loadoutIndex}: key='{text}' name='{text2}'");
if (!string.IsNullOrEmpty(text2))
{
if (!windowLoadoutNames.TryGetValue(window, out var value3))
{
value3 = new Dictionary<int, string>();
windowLoadoutNames[window] = value3;
}
value3[loadoutIndex] = text2;
return text2;
}
}
}
}
}
catch (Exception)
{
}
return $"Loadout {loadoutIndex + 1}";
}
private static void SetLoadoutName(GearDetailsWindow window, int loadoutIndex, string newName)
{
try
{
if (!windowLoadoutNames.TryGetValue(window, out var value))
{
value = new Dictionary<int, string>();
windowLoadoutNames[window] = value;
}
if (!string.IsNullOrEmpty(newName))
{
value[loadoutIndex] = newName;
}
else
{
value.Remove(loadoutIndex);
}
try
{
IUpgradable upgradablePrefab = window.UpgradablePrefab;
if (upgradablePrefab != null)
{
Type? typeFromHandle = typeof(PlayerData);
object obj = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
object obj2 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj, new object[1] { upgradablePrefab });
if (obj2 != null)
{
object? obj3 = obj2.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj2);
IUpgradable val = (IUpgradable)((obj3 is IUpgradable) ? obj3 : null);
if (val != null)
{
string text = $"{val.Info.ID}_{loadoutIndex}";
SparrohPlugin.Logger.LogInfo((object)$"Saving name for gear {val.Info.ID} slot {loadoutIndex}: key='{text}' name='{newName}'");
if (!string.IsNullOrEmpty(newName))
{
PlayerPrefs.SetString("LoadoutName_" + text, newName);
PlayerPrefs.Save();
PlayerPrefs.SetString($"ImprovedLoadouts_Name_{val.Info.ID}_{loadoutIndex}", newName);
PlayerPrefs.Save();
}
else
{
PlayerPrefs.DeleteKey("LoadoutName_" + text);
PlayerPrefs.Save();
}
}
}
}
}
catch (Exception)
{
}
try
{
Type type = AccessTools.TypeByName("HoverInfoDisplay");
object obj4 = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
if (obj4 == null)
{
return;
}
FieldInfo field = type.GetField("currentInfo", BindingFlags.Instance | BindingFlags.NonPublic);
MethodInfo method = type.GetMethod("SetInfo", BindingFlags.Instance | BindingFlags.Public);
if (!(field != null) || !(method != null))
{
return;
}
object value2 = field.GetValue(obj4);
if (((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array && loadoutIndex < array.Length)
{
object? value3 = array.GetValue(loadoutIndex);
LoadoutHoverInfo val2 = (LoadoutHoverInfo)((value3 is LoadoutHoverInfo) ? value3 : null);
if (value2 != null && value2 == val2)
{
field.SetValue(obj4, null);
method.Invoke(obj4, new object[1] { val2 });
}
}
}
catch (Exception)
{
try
{
Type type2 = AccessTools.TypeByName("HoverInfoDisplay");
object obj5 = type2.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
if (obj5 != null)
{
type2.GetMethod("Deactivate", BindingFlags.Instance | BindingFlags.Public)?.Invoke(obj5, new object[0]);
}
}
catch (Exception)
{
}
}
}
catch (Exception)
{
}
}
private static int FindHoveredButton(GearDetailsWindow window)
{
try
{
try
{
Type type = AccessTools.TypeByName("HoverInfoDisplay");
object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
if (obj != null)
{
object obj2 = type.GetField("currentInfo", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
if (obj2 != null && ((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array)
{
for (int i = 0; i < array.Length; i++)
{
object? value = array.GetValue(i);
LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null);
if ((Object)(object)val != (Object)null && val == obj2)
{
return i;
}
}
}
}
}
catch (Exception)
{
}
try
{
Type type2 = AccessTools.TypeByName("UnityEngine.EventSystems.EventSystem");
object obj3 = type2.GetProperty("current", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
if (obj3 != null)
{
object? obj4 = type2.GetProperty("currentSelectedGameObject", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj3);
GameObject val2 = (GameObject)((obj4 is GameObject) ? obj4 : null);
if ((Object)(object)val2 != (Object)null)
{
LoadoutHoverInfo componentInParent = val2.GetComponentInParent<LoadoutHoverInfo>();
if ((Object)(object)componentInParent != (Object)null && ((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array2)
{
for (int j = 0; j < array2.Length; j++)
{
if (array2.GetValue(j) == componentInParent)
{
return j;
}
}
}
}
}
}
catch (Exception)
{
}
try
{
if (((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array3)
{
for (int k = 0; k < array3.Length; k++)
{
object? value2 = array3.GetValue(k);
LoadoutHoverInfo val3 = (LoadoutHoverInfo)((value2 is LoadoutHoverInfo) ? value2 : null);
if ((Object)(object)val3 != (Object)null)
{
object? obj5 = ((object)val3).GetType().GetProperty("gameObject")?.GetValue(val3);
_ = (Object)((obj5 is GameObject) ? obj5 : null) != (Object)null;
}
}
}
}
catch (Exception)
{
}
}
catch (Exception)
{
}
return -1;
}
[HarmonyPatch(typeof(LoadoutHoverInfo), "GetTitle")]
[HarmonyPostfix]
public static void GetTitlePostfix(ref LoadoutHoverInfo __instance, ref bool __result, out string title, out Color color)
{
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: 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_0096: 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_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
try
{
GearDetailsWindow componentInParent = ((Component)__instance).GetComponentInParent<GearDetailsWindow>();
if ((Object)(object)componentInParent != (Object)null && ((object)componentInParent).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(componentInParent) is Array array)
{
for (int i = 0; i < array.Length; i++)
{
object? value = array.GetValue(i);
LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null);
if ((Object)(object)val != (Object)null && val == __instance)
{
string loadoutName = GetLoadoutName(componentInParent, i);
if (!string.IsNullOrEmpty(loadoutName))
{
title = loadoutName;
color = Color.white;
__result = true;
}
else
{
title = $"Loadout {i + 1}";
color = Color.white;
__result = true;
}
return;
}
}
}
title = TextBlocks.GetString("loadout");
color = Color.white;
__result = true;
}
catch (Exception)
{
title = TextBlocks.GetString("loadout");
color = Color.white;
__result = true;
}
}
[HarmonyPatch(typeof(GearDetailsWindow), "Update")]
[HarmonyPostfix]
public static void GearDetailsWindowUpdatePostfix(ref GearDetailsWindow __instance)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: 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)
try
{
if (LoadoutRenameDialog.IsActive)
{
return;
}
Keyboard current = Keyboard.current;
if (current == null || !((ButtonControl)current[RenameKey]).wasPressedThisFrame)
{
return;
}
Vector2.op_Implicit(((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue());
if (!(((object)__instance).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is Array array))
{
return;
}
for (int i = 0; i < array.Length; i++)
{
object? value = array.GetValue(i);
LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null);
if ((Object)(object)val != (Object)null && IsHovered(val))
{
StartRenameProcess(val, i, __instance);
break;
}
}
}
catch (Exception)
{
}
}
private static bool IsHovered(LoadoutHoverInfo button)
{
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
try
{
Type type = AccessTools.TypeByName("HoverInfoDisplay");
object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
if (obj != null && type.GetField("currentInfo", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj) == button)
{
return true;
}
try
{
Camera main = Camera.main;
if ((Object)(object)main != (Object)null)
{
Vector2 val = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue();
RaycastHit val2 = default(RaycastHit);
if (Physics.Raycast(main.ScreenPointToRay(Vector2.op_Implicit(val)), ref val2, float.PositiveInfinity))
{
Collider collider = ((RaycastHit)(ref val2)).collider;
GameObject val3 = ((collider != null) ? ((Component)collider).gameObject : null);
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.GetComponentInParent<LoadoutHoverInfo>() == (Object)(object)button)
{
return true;
}
}
Type type2 = AccessTools.TypeByName("UnityEngine.EventSystems.PointerEventData");
if (type2 != null)
{
object obj2 = Activator.CreateInstance(type2, Object.op_Implicit((Object)(object)EventSystem.current));
type2.GetField("position")?.SetValue(obj2, val);
List<RaycastResult> list = new List<RaycastResult>();
try
{
Canvas[] array = Object.FindObjectsOfType<Canvas>();
foreach (Canvas val4 in array)
{
if (!((Object)(object)val4 != (Object)null))
{
continue;
}
GraphicRaycaster component = ((Component)val4).GetComponent<GraphicRaycaster>();
if (!((Object)(object)component != (Object)null))
{
continue;
}
MethodInfo method = ((object)component).GetType().GetMethod("Raycast", BindingFlags.Instance | BindingFlags.Public);
if (!(method != null))
{
continue;
}
list.Clear();
method.Invoke(component, new object[2] { obj2, list });
foreach (RaycastResult item in list)
{
RaycastResult current = item;
if ((Object)(object)((RaycastResult)(ref current)).gameObject != (Object)null && (Object)(object)((RaycastResult)(ref current)).gameObject.GetComponentInParent<LoadoutHoverInfo>() == (Object)(object)button)
{
return true;
}
}
}
}
finally
{
list.Clear();
}
}
}
}
catch (Exception)
{
}
try
{
object obj3 = ((object)button).GetType().GetProperty("Active", BindingFlags.Instance | BindingFlags.Public)?.GetValue(button);
bool flag = default(bool);
int num;
if (obj3 is bool)
{
flag = (bool)obj3;
num = 1;
}
else
{
num = 0;
}
if (((uint)num & (flag ? 1u : 0u)) != 0)
{
return true;
}
}
catch (Exception)
{
}
return false;
}
catch (Exception)
{
return false;
}
}
private static void StartRenameProcess(LoadoutHoverInfo button, int loadoutIndex, GearDetailsWindow window)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
try
{
string text = GetLoadoutName(window, loadoutIndex);
if (string.IsNullOrEmpty(text))
{
text = $"Loadout {loadoutIndex + 1}";
}
LoadoutRenameDialog.Show(((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue(), text, delegate(string newName)
{
SetLoadoutName(window, loadoutIndex, newName);
}, delegate
{
}, window, loadoutIndex);
}
catch (Exception)
{
}
}
[HarmonyPatch(typeof(GearData), "SaveLoadout")]
[HarmonyPostfix]
public static void SaveLoadoutNamesPostfix(ref GearData __instance, int index)
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
try
{
IUpgradable gear = __instance.Gear;
if (gear == null)
{
return;
}
Type type = AccessTools.TypeByName("GearDetailsWindow");
PropertyInfo property = type.GetProperty("Active", BindingFlags.Static | BindingFlags.Public);
object obj = null;
if (property != null)
{
obj = property.GetValue(null);
}
if (obj == null)
{
Object[] array = Object.FindObjectsOfType(type);
if (array.Length != 0)
{
obj = array[0];
}
}
if (obj != null && windowLoadoutNames.TryGetValue((GearDetailsWindow)obj, out var value) && value.TryGetValue(index, out var value2))
{
string text = $"{gear.Info.ID}_{((object)gear).GetHashCode()}_{index}";
SparrohPlugin.Logger.LogInfo((object)$"Persisting name for gear {gear.Info.ID} slot {index}: key='{text}' name='{value2}'");
PlayerPrefs.SetString("LoadoutName_" + text, value2);
PlayerPrefs.Save();
}
}
catch (Exception)
{
}
}
}
[BepInPlugin("sparroh.loadoutimprovements", "LoadoutImprovements", "1.2.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class SparrohPlugin : BaseUnityPlugin
{
public const string PluginGUID = "sparroh.loadoutimprovements";
public const string PluginName = "LoadoutImprovements";
public const string PluginVersion = "1.2.1";
private ConfigEntry<Key> ScrollLeftKey;
private ConfigEntry<Key> ScrollRightKey;
private ConfigEntry<Key> LoadoutRenameKey;
internal static ManualLogSource Logger;
public static SparrohPlugin Instance;
private FileSystemWatcher _configWatcher;
private volatile bool _configDirty;
private float _configReloadAt = -1f;
private const float ConfigReloadDebounce = 0.25f;
private void Awake()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_0097: 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_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
try
{
Logger = ((BaseUnityPlugin)this).Logger;
Instance = this;
Harmony val = new Harmony("sparroh.loadoutimprovements");
try
{
LoadoutExpanderMod._loadoutButtonsField = AccessTools.Field(typeof(GearDetailsWindow), "loadoutButtons");
LoadoutExpanderMod._updateIconMethod = AccessTools.Method(typeof(GearDetailsWindow), "UpdateLoadoutIcon", (Type[])null, (Type[])null);
}
catch (Exception ex)
{
Logger.LogError((object)("Failed to setup LoadoutExpander reflection: " + ex.Message));
}
try
{
ScrollLeftKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Keybinds", "Scroll Loadout Left", (Key)7, "Key to scroll to the left loadout page");
LoadoutExpanderMod.ScrollLeftKey = ScrollLeftKey.Value;
ScrollLeftKey.SettingChanged += delegate
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
LoadoutExpanderMod.ScrollLeftKey = ScrollLeftKey.Value;
};
ScrollRightKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Keybinds", "Scroll Loadout Right", (Key)8, "Key to scroll to the right loadout page");
LoadoutExpanderMod.ScrollRightKey = ScrollRightKey.Value;
ScrollRightKey.SettingChanged += delegate
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
LoadoutExpanderMod.ScrollRightKey = ScrollRightKey.Value;
};
LoadoutRenameKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Keybinds", "Rename Loadout", (Key)32, "Key to rename the hovered loadout");
LoadoutHoverInfoPatches.RenameKey = LoadoutRenameKey.Value;
LoadoutRenameKey.SettingChanged += delegate
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
LoadoutHoverInfoPatches.RenameKey = LoadoutRenameKey.Value;
};
LoadoutPreviewMod.enableTextMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Loadout Preview", true, "If true, show upgrade list on hover");
LoadoutPreviewMod.enableTextMode.SettingChanged += delegate
{
LoadoutPreviewMod.OnConfigChanged();
};
LoadoutPreviewMod.UpdatePreviewMode();
SetupConfigHotReload();
}
catch (Exception ex2)
{
Logger.LogError((object)("Failed to setup configuration bindings: " + ex2.Message));
}
try
{
LoadoutPreviewMod.ApplyPatches(val);
}
catch (Exception ex3)
{
Logger.LogError((object)("Failed to apply LoadoutPreviewMod patches: " + ex3.Message));
}
try
{
val.PatchAll();
}
catch (Exception ex4)
{
Logger.LogError((object)("Failed to apply Harmony patches: " + ex4.Message));
}
}
catch (Exception ex5)
{
Logger.LogError((object)("Critical error during mod initialization: " + ex5.Message + "\n" + ex5.StackTrace));
}
Logger.LogInfo((object)"LoadoutImprovements loaded successfully.");
}
private void SetupConfigHotReload()
{
try
{
string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
string directoryName = Path.GetDirectoryName(configFilePath);
string fileName = Path.GetFileName(configFilePath);
if (string.IsNullOrEmpty(directoryName) || string.IsNullOrEmpty(fileName))
{
Logger.LogWarning((object)"Could not resolve config path for hot reload.");
return;
}
_configWatcher = new FileSystemWatcher(directoryName, fileName)
{
NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
EnableRaisingEvents = true
};
_configWatcher.Changed += OnConfigFileChanged;
_configWatcher.Created += OnConfigFileChanged;
_configWatcher.Renamed += OnConfigFileChanged;
Logger.LogInfo((object)("Config hot reload enabled for " + fileName));
}
catch (Exception ex)
{
Logger.LogError((object)("Failed to setup config hot reload: " + ex.Message));
}
}
private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
{
_configDirty = true;
}
private void ProcessPendingConfigReload()
{
//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_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
if (_configDirty)
{
_configDirty = false;
_configReloadAt = Time.unscaledTime + 0.25f;
}
if (_configReloadAt < 0f || Time.unscaledTime < _configReloadAt)
{
return;
}
_configReloadAt = -1f;
try
{
((BaseUnityPlugin)this).Config.Reload();
if (ScrollLeftKey != null)
{
LoadoutExpanderMod.ScrollLeftKey = ScrollLeftKey.Value;
}
if (ScrollRightKey != null)
{
LoadoutExpanderMod.ScrollRightKey = ScrollRightKey.Value;
}
if (LoadoutRenameKey != null)
{
LoadoutHoverInfoPatches.RenameKey = LoadoutRenameKey.Value;
}
if (LoadoutPreviewMod.enableTextMode != null)
{
LoadoutPreviewMod.UpdatePreviewMode();
}
Logger.LogInfo((object)"Config reloaded from disk.");
}
catch (Exception ex)
{
Logger.LogError((object)("Failed to reload config: " + ex.Message));
}
}
private void OnDestroy()
{
try
{
if (_configWatcher != null)
{
_configWatcher.EnableRaisingEvents = false;
_configWatcher.Changed -= OnConfigFileChanged;
_configWatcher.Created -= OnConfigFileChanged;
_configWatcher.Renamed -= OnConfigFileChanged;
_configWatcher.Dispose();
_configWatcher = null;
}
}
catch (Exception ex)
{
Logger.LogError((object)("Failed to dispose config watcher: " + ex.Message));
}
try
{
LoadoutPreviewMod.Destroy();
}
catch (Exception ex2)
{
Logger.LogError((object)("Failed to destroy LoadoutPreviewMod: " + ex2.Message));
}
}
private void Update()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
try
{
ProcessPendingConfigReload();
if (Keyboard.current != null)
{
if (((ButtonControl)Keyboard.current[LoadoutExpanderMod.ScrollRightKey]).wasPressedThisFrame)
{
LoadoutExpanderMod.ScrollRight();
}
else if (((ButtonControl)Keyboard.current[LoadoutExpanderMod.ScrollLeftKey]).wasPressedThisFrame)
{
LoadoutExpanderMod.ScrollLeft();
}
}
}
catch (Exception ex)
{
Logger.LogError((object)("Critical error in Update(): " + ex.Message));
}
}
}
public class TextPreview : MonoBehaviour
{
private CanvasGroup canvasGroup;
private readonly List<UIText> textElements = new List<UIText>();
private UIPanel panel;
private void Awake()
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
UITheme.Initialize();
canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
canvasGroup.alpha = 0.95f;
Image val = ((Component)this).gameObject.GetComponent<Image>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)this).gameObject.AddComponent<Image>();
}
((Graphic)val).color = UIColors.TooltipBg;
UIFactory.ApplyWhiteSprite(val);
Outline obj = ((Component)this).gameObject.AddComponent<Outline>();
((Shadow)obj).effectColor = UIColors.Border;
((Shadow)obj).effectDistance = new Vector2(1f, -1f);
UIFactory.AddVerticalLayout(((Component)this).gameObject, UITheme.S(UITheme.SpacingTight), UITheme.ScaledPadding(10, 10, 10, 10), (TextAnchor)0, true, false, true, true);
UIFactory.AddContentSizeFitter(((Component)this).gameObject, (FitMode)2, (FitMode)2);
}
public void Setup(List<LoadoutPreviewMod.UpgradePlacement> placements)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
Clear();
foreach (LoadoutPreviewMod.UpgradePlacement placement in placements)
{
if (placement.Upgrade != null)
{
UIText val = UIText.Create(((Component)this).transform, "TextElement", placement.Upgrade.Upgrade.Name, UITheme.ScaledFontSmall, (Color?)placement.Upgrade.Upgrade.Color, (TextAlignmentOptions)513, false);
GameObject gameObject = val.GameObject;
float? num = UITheme.S(18f);
UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, (float?)null);
textElements.Add(val);
}
}
}
private void Clear()
{
foreach (UIText textElement in textElements)
{
if (textElement != null && (Object)(object)textElement.GameObject != (Object)null)
{
Object.Destroy((Object)(object)textElement.GameObject);
}
}
textElements.Clear();
}
public void SetPosition(Vector2 position)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
((RectTransform)((Component)this).transform).anchoredPosition = position;
}
public void Show()
{
((Component)this).gameObject.SetActive(true);
}
public void Hide()
{
((Component)this).gameObject.SetActive(false);
}
}
namespace LoadoutImprovements
{
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "LoadoutImprovements";
public const string PLUGIN_NAME = "LoadoutImprovements";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}