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; using Sparroh.UI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; 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("BatchScrapping")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BatchScrapping")] [assembly: AssemblyTitle("BatchScrapping")] [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 InstantPatches { internal static ConfigEntry EnableFixedTimer; internal static ConfigEntry FixedTimerDuration; internal static ConfigEntry EnableInstantScrapping; internal static bool s_EnableInstantScrapping; internal static bool s_EnableFixedTimer; internal static float s_FixedTimerDuration; private static FileSystemWatcher configWatcher; private static Harmony _harmony; private const float InstantDuration = 0.05f; public static bool ShouldModifyDuration { get { if (EnableInstantScrapping == null || !EnableInstantScrapping.Value) { if (EnableFixedTimer != null) { return EnableFixedTimer.Value; } return false; } return true; } } public static void Initialize(ConfigEntry enableFixed, ConfigEntry fixedDur, ConfigEntry enableInst) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown try { EnableFixedTimer = enableFixed; FixedTimerDuration = fixedDur; EnableInstantScrapping = enableInst; s_EnableInstantScrapping = EnableInstantScrapping.Value; s_EnableFixedTimer = EnableFixedTimer.Value; s_FixedTimerDuration = FixedTimerDuration.Value; try { SetupFileWatchers(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to setup file watchers: " + ex.Message)); } _harmony = new Harmony("sparroh.instantscrapping"); MethodInfo methodInfo = AccessTools.Method(typeof(GearUpgradeUI), "HasUnlockAction", new Type[1] { typeof(UnlockActionParams).MakeByRefType() }, (Type[])null); if (methodInfo != null) { try { _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(InstantScrapPatches), "HasUnlockActionPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); SparrohPlugin.Logger.LogInfo((object)"InstantScrapping: patched GearUpgradeUI.HasUnlockAction"); return; } catch (Exception ex2) { SparrohPlugin.Logger.LogError((object)("Failed to patch HasUnlockAction: " + ex2.Message)); return; } } SparrohPlugin.Logger.LogError((object)"InstantScrapping: could not find GearUpgradeUI.HasUnlockAction(out UnlockActionParams). Instant scrap disabled."); } catch (Exception ex3) { SparrohPlugin.Logger.LogError((object)("Critical error during InstantScrapping initialization: " + ex3.Message)); } } private static void SetupFileWatchers() { configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.batchscrapping.cfg"); configWatcher.Changed += delegate { try { ((ConfigEntryBase)EnableInstantScrapping).ConfigFile.Reload(); s_EnableInstantScrapping = EnableInstantScrapping.Value; s_EnableFixedTimer = EnableFixedTimer.Value; s_FixedTimerDuration = FixedTimerDuration.Value; } catch (Exception ex) { SparrohPlugin.Logger.LogWarning((object)("Config reload failed: " + ex.Message)); } }; configWatcher.EnableRaisingEvents = true; } public static void Destroy() { if (configWatcher != null) { configWatcher.EnableRaisingEvents = false; configWatcher.Dispose(); configWatcher = null; } Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; } public static float GetModifiedDuration(float original) { if (EnableInstantScrapping != null && EnableInstantScrapping.Value) { return 0.05f; } if (EnableFixedTimer != null && EnableFixedTimer.Value) { return Mathf.Max(0.05f, FixedTimerDuration.Value); } return original; } } public static class InstantScrapPatches { public static void HasUnlockActionPostfix(ref UnlockActionParams data) { try { if (data.OnSecondaryComplete != null && InstantPatches.ShouldModifyDuration) { data.SecondaryDuration = InstantPatches.GetModifiedDuration(data.SecondaryDuration); } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in HasUnlockActionPostfix: " + ex.Message)); } } } [BepInPlugin("sparroh.batchscrapping", "BatchScrapping", "2.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.batchscrapping"; public const string PluginName = "BatchScrapping"; public const string PluginVersion = "2.1.0"; private ConfigEntry TrashMarkKey; private ConfigEntry EnableInstantScrapping; private ConfigEntry EnableFixedTimer; private ConfigEntry FixedTimerDuration; internal static ManualLogSource Logger; public static SparrohPlugin Instance; private bool _barRegistered; private bool _lastUndoCan; private int _lastUndoCount = -1; 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_0044: 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_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Expected O, but got Unknown //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Expected O, but got Unknown //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Expected O, but got Unknown //IL_0308: Expected O, but got Unknown try { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; Harmony val = new Harmony("sparroh.batchscrapping"); try { TrashMarkKey = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "Mark for Trash", (Key)34, "Key to toggle trash mark on upgrades"); ScrapHandlingMod.currentTrashKey = TrashMarkKey.Value; TrashMarkKey.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) ScrapHandlingMod.currentTrashKey = TrashMarkKey.Value; }; ScrapHandlingMod.ScrapMarkedAction = delegate { ScrapHandlingMod.TryScrapMarkedUpgrades((MonoBehaviour)(object)this); }; ScrapHandlingMod.ScrapNonFavoriteAction = delegate { ScrapHandlingMod.TryScrapNonFavoriteUpgrades((MonoBehaviour)(object)this); }; EnableInstantScrapping = ((BaseUnityPlugin)this).Config.Bind("General", "Instant Scrap", false, "Enable instant scrapping without hold timer"); EnableFixedTimer = ((BaseUnityPlugin)this).Config.Bind("General", "Fixed Scrap Time", false, "Use fixed scrap timer instead of default (ignored when Instant Scrap is on)"); FixedTimerDuration = ((BaseUnityPlugin)this).Config.Bind("General", "Scrap Duration", 1f, "Duration in seconds for fixed scrap timer"); } catch (Exception ex) { Logger.LogError((object)("Failed to setup configuration bindings: " + ex.Message)); } try { InstantPatches.Initialize(EnableFixedTimer, FixedTimerDuration, EnableInstantScrapping); } catch (Exception ex2) { Logger.LogError((object)("Failed to initialize InstantScrapping: " + ex2.Message)); } try { val.PatchAll(); } catch (Exception ex3) { Logger.LogError((object)("Failed to apply Harmony patches: " + ex3.Message)); } try { MethodInfo methodInfo = AccessTools.Method(typeof(GearDetailsWindow), "Update", (Type[])null, (Type[])null); if (methodInfo != null) { val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Patches), "UpdatePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.Method(typeof(GearUpgradeUI), "UpdateFavoriteIcon", (Type[])null, (Type[])null); if (methodInfo2 != null) { val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "UpdateFavoriteIconPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo3 = AccessTools.Method(typeof(GearUpgradeUI), "OnAdditionalAction", new Type[2] { typeof(int), typeof(bool).MakeByRefType() }, (Type[])null); if (methodInfo3 != null) { val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "OnAdditionalActionPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo4 = AccessTools.Method(typeof(GearUpgradeUI), "EnableGridView", new Type[1] { typeof(bool) }, (Type[])null); if (methodInfo4 != null) { val.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "EnableGridViewPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo5 = AccessTools.Method(typeof(GearUpgradeUI), "Dismantle", (Type[])null, (Type[])null); if (methodInfo5 != null) { val.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(ScrapUndoPatches), "DismantlePrefix", (Type[])null), new HarmonyMethod(typeof(ScrapUndoPatches), "DismantlePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)"Patched GearUpgradeUI.Dismantle for scrap undo."); } else { Logger.LogError((object)"Could not find GearUpgradeUI.Dismantle — single-scrap undo unavailable."); } } catch (Exception ex4) { Logger.LogError((object)("Failed to apply scrap patches: " + ex4.Message)); } } catch (Exception ex5) { Logger.LogError((object)("Critical error during mod initialization: " + ex5.Message + "\n" + ex5.StackTrace)); } Logger.LogInfo((object)"BatchScrapping v2.1.0 loaded successfully."); } private void Update() { GearActionBar.Tick(); if (!GearActionBar.IsGearMenuOpen()) { return; } if (!_barRegistered) { GearActionBar.Register("scrap_marked", "Scrap Marked", 120, (Action)delegate { UIDialog.Confirm("Scrap Marked", "Scrap all trash-marked upgrades? This can be undone.", (Action)delegate { ScrapHandlingMod.ScrapMarkedAction?.Invoke(); }, (Action)null, "Confirm", "Cancel"); }, (UIButtonStyle)0); GearActionBar.Register("scrap_nonfav", "Scrap No-Fav", 130, (Action)delegate { UIDialog.Confirm("Scrap Non-Favorite", "Scrap ALL non-favorite upgrades? This can be undone.", (Action)delegate { ScrapHandlingMod.ScrapNonFavoriteAction?.Invoke(); }, (Action)null, "Confirm", "Cancel"); }, (UIButtonStyle)2); GearActionBar.Register("undo_scrap", "Undo Scrap", 140, (Action)delegate { UndoPatches.TryUndo(); }, (UIButtonStyle)1); _barRegistered = true; _lastUndoCan = !UndoPatches.CanUndo; _lastUndoCount = -1; } bool canUndo = UndoPatches.CanUndo; int undoCount = UndoPatches.UndoCount; if (canUndo != _lastUndoCan || undoCount != _lastUndoCount) { _lastUndoCan = canUndo; _lastUndoCount = undoCount; GearActionBar.SetInteractable("undo_scrap", canUndo); GearActionBar.SetText("undo_scrap", canUndo ? $"Undo ({undoCount})" : "Undo"); } } private void OnDestroy() { try { InstantPatches.Destroy(); UndoPatches.Clear(); GearActionBar.Unregister("scrap_marked"); GearActionBar.Unregister("scrap_nonfav"); GearActionBar.Unregister("undo_scrap"); _barRegistered = false; } catch (Exception ex) { Logger.LogError((object)("Failed to destroy BatchScrapping UI: " + ex.Message)); } } } public static class ScrapHandlingMod { private static bool isScrapping; private static bool wasScrappingSkins; private const float HOLD_DURATION = 1f; private const int BATCH_SIZE = 1000000; private const float BATCH_INTERVAL = 0f; private const float SPECIAL_REWARD_CHANCE = 0.02f; public static Key currentTrashKey; public static Action ScrapMarkedAction; public static Action ScrapNonFavoriteAction; public static Sprite starSprite; private const byte FavoriteFlag = 1; private const byte TrashMarkFlag = 32; public static bool IsScrapping => isScrapping; public static IEnumerator ScrapMarkedUpgrades() { Dictionary dictionary = new Dictionary(); int num = 0; bool flag; List list; bool flag2; try { if (isScrapping) { SparrohPlugin.Logger.LogWarning((object)"ScrapMarkedUpgrades: Already scrapping, aborting."); yield break; } isScrapping = true; SparrohPlugin.Logger.LogInfo((object)"Starting ScrapMarkedUpgrades operation."); GearDetailsWindow val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { SparrohPlugin.Logger.LogError((object)"ScrapMarkedUpgrades: GearDetailsWindow not found."); isScrapping = false; yield break; } IUpgradable upgradablePrefab = val.UpgradablePrefab; if (upgradablePrefab == null) { SparrohPlugin.Logger.LogError((object)"ScrapMarkedUpgrades: UpgradablePrefab is null."); isScrapping = false; yield break; } bool num2 = (bool)AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").GetValue(val); flag = num2; IEnumerable enumerable = (num2 ? PlayerData.GetAllSkins(upgradablePrefab, true) : PlayerData.GetAllUpgrades(upgradablePrefab, true)); int num3 = 0; foreach (UpgradeInfo item in enumerable) { if (item?.Instances != null) { num3 += item.Instances.Count; } } list = new List(num3); foreach (UpgradeInfo item2 in enumerable) { if (item2?.Instances == null) { continue; } foreach (UpgradeInstance instance in item2.Instances) { if (instance != null && IsTrashMarked(instance)) { list.Add(instance); } } } if (list.Count == 0) { SparrohPlugin.Logger.LogInfo((object)"ScrapMarkedUpgrades: No marked upgrades found."); isScrapping = false; yield break; } UndoPatches.BeginBatch($"Scrap Marked ({list.Count})"); foreach (UpgradeInstance item3 in list) { UndoPatches.AddToBatch(item3); } SparrohPlugin.Logger.LogInfo((object)$"ScrapMarkedUpgrades: Processing {list.Count} upgrades."); PlayerResource key2 = default(PlayerResource); PlayerResource key3 = default(PlayerResource); foreach (KeyValuePair> item4 in (from inst in list group inst by inst.Upgrade.Rarity).ToDictionary((IGrouping g) => g.Key, (IGrouping g) => g.ToList())) { Rarity key = item4.Key; int count = item4.Value.Count; ref RarityData rarity = ref Global.GetRarity(key); int num4 = rarity.upgradeScripCost / 6; dictionary.TryGetValue(Global.Instance.ScripResource, out var value); dictionary[Global.Instance.ScripResource] = value + num4 * count; if (!flag) { dictionary.TryGetValue(rarity.scrapResource, out var value2); dictionary[rarity.scrapResource] = value2 + 2 * count; if (PlayerResource.TryGetResource("strange_comp", ref key2)) { int num5 = Mathf.FloorToInt((float)count * 0.02f); dictionary.TryGetValue(key2, out var value3); dictionary[key2] = value3 + num5; } } else if (PlayerResource.TryGetResource("oyster", ref key3)) { int num6 = Mathf.FloorToInt((float)count * 0.02f); dictionary.TryGetValue(key3, out var value4); dictionary[key3] = value4 + num6; } } flag2 = true; } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("ScrapMarkedUpgrades: Setup failed: " + ex.Message)); UndoPatches.CancelBatch(); isScrapping = false; yield break; } if (flag2 && list != null) { for (int num7 = 0; num7 < list.Count; num7 += 1000000) { int num8 = Mathf.Min(num7 + 1000000, list.Count); for (int num9 = num7; num9 < num8; num9++) { UpgradeInstance val2 = list[num9]; if (val2 != null && !((Object)(object)val2.Upgrade == (Object)null)) { try { PlayerData.UnequipFromAll(val2); } catch { } val2.Destroy(); num++; } } } } try { foreach (KeyValuePair item5 in dictionary) { PlayerData.Instance.AddResource(item5.Key, item5.Value, true); } } catch (Exception ex2) { SparrohPlugin.Logger.LogError((object)("ScrapMarkedUpgrades: Failed to add resources: " + ex2.Message)); } if (num > 0) { UndoPatches.EndBatch(); try { wasScrappingSkins = flag; RefreshOpenWindows(); } catch (Exception ex3) { SparrohPlugin.Logger.LogError((object)("ScrapMarkedUpgrades: Failed to refresh windows: " + ex3.Message)); } } else { UndoPatches.CancelBatch(); } isScrapping = false; } public static bool IsFavorite(UpgradeInstance instance) { if (instance == null) { return false; } return ((byte)AccessTools.Field(typeof(UpgradeInstance), "flags").GetValue(instance) & 1) != 0; } public static bool IsTrashMarked(UpgradeInstance instance) { if (instance == null) { return false; } return ((byte)AccessTools.Field(typeof(UpgradeInstance), "flags").GetValue(instance) & 0x20) != 0; } public static void SetTrashMark(UpgradeInstance instance, bool marked) { if (instance != null) { FieldInfo fieldInfo = AccessTools.Field(typeof(UpgradeInstance), "flags"); byte b = (byte)fieldInfo.GetValue(instance); if (marked) { b |= 0x20; b &= 0xFE; } else { b &= 0xDF; } fieldInfo.SetValue(instance, b); } } public static void SetFavorite(UpgradeInstance instance, bool favorite) { if (instance != null) { FieldInfo fieldInfo = AccessTools.Field(typeof(UpgradeInstance), "flags"); byte b = (byte)fieldInfo.GetValue(instance); if (favorite) { b |= 1; b &= 0xDF; } else { b &= 0xFE; } fieldInfo.SetValue(instance, b); } } public static void TryScrapMarkedUpgrades(MonoBehaviour owner) { GearDetailsWindow val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return; } IUpgradable upgradablePrefab = val.UpgradablePrefab; if (upgradablePrefab == null) { return; } List obj = (((bool)AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").GetValue(val)) ? PlayerData.GetAllSkins(upgradablePrefab, true) : PlayerData.GetAllUpgrades(upgradablePrefab, true)); bool flag = false; foreach (UpgradeInfo item in obj) { if (item?.Instances != null && item.Instances.Any((UpgradeInstance inst) => inst != null && IsTrashMarked(inst))) { flag = true; break; } } if (flag) { owner.StartCoroutine(ScrapMarkedUpgrades()); } } public static IEnumerator ScrapNonFavoriteUpgrades() { Dictionary dictionary = new Dictionary(); int num = 0; bool flag; List list; bool flag2; try { if (isScrapping) { SparrohPlugin.Logger.LogWarning((object)"ScrapNonFavoriteUpgrades: Already scrapping, aborting."); yield break; } isScrapping = true; SparrohPlugin.Logger.LogInfo((object)"Starting ScrapNonFavoriteUpgrades operation."); GearDetailsWindow val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { SparrohPlugin.Logger.LogError((object)"ScrapNonFavoriteUpgrades: GearDetailsWindow not found."); isScrapping = false; yield break; } IUpgradable upgradablePrefab = val.UpgradablePrefab; if (upgradablePrefab == null) { SparrohPlugin.Logger.LogError((object)"ScrapNonFavoriteUpgrades: UpgradablePrefab is null."); isScrapping = false; yield break; } bool num2 = (bool)AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").GetValue(val); flag = num2; IEnumerable enumerable = (num2 ? PlayerData.GetAllSkins(upgradablePrefab, true) : PlayerData.GetAllUpgrades(upgradablePrefab, true)); int num3 = 0; foreach (UpgradeInfo item in enumerable) { if (item?.Instances != null) { num3 += item.Instances.Count; } } list = new List(num3); foreach (UpgradeInfo item2 in enumerable) { if (item2?.Instances == null) { continue; } foreach (UpgradeInstance instance in item2.Instances) { if (instance != null && !IsFavorite(instance)) { list.Add(instance); } } } if (list.Count == 0) { SparrohPlugin.Logger.LogInfo((object)"ScrapNonFavoriteUpgrades: No non-favorite upgrades found."); isScrapping = false; yield break; } UndoPatches.BeginBatch($"Scrap Non-Favorite ({list.Count})"); foreach (UpgradeInstance item3 in list) { UndoPatches.AddToBatch(item3); } SparrohPlugin.Logger.LogInfo((object)$"ScrapNonFavoriteUpgrades: Processing {list.Count} upgrades."); PlayerResource key2 = default(PlayerResource); PlayerResource key3 = default(PlayerResource); foreach (KeyValuePair> item4 in (from inst in list group inst by inst.Upgrade.Rarity).ToDictionary((IGrouping g) => g.Key, (IGrouping g) => g.ToList())) { Rarity key = item4.Key; int count = item4.Value.Count; ref RarityData rarity = ref Global.GetRarity(key); int num4 = rarity.upgradeScripCost / 6; dictionary.TryGetValue(Global.Instance.ScripResource, out var value); dictionary[Global.Instance.ScripResource] = value + num4 * count; if (!flag) { dictionary.TryGetValue(rarity.scrapResource, out var value2); dictionary[rarity.scrapResource] = value2 + 2 * count; if (PlayerResource.TryGetResource("strange_comp", ref key2)) { int num5 = Mathf.FloorToInt((float)count * 0.02f); dictionary.TryGetValue(key2, out var value3); dictionary[key2] = value3 + num5; } } else if (PlayerResource.TryGetResource("oyster", ref key3)) { int num6 = Mathf.FloorToInt((float)count * 0.02f); dictionary.TryGetValue(key3, out var value4); dictionary[key3] = value4 + num6; } } flag2 = true; } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("ScrapNonFavoriteUpgrades: Setup failed: " + ex.Message)); UndoPatches.CancelBatch(); isScrapping = false; yield break; } if (flag2 && list != null) { for (int num7 = 0; num7 < list.Count; num7 += 1000000) { int num8 = Mathf.Min(num7 + 1000000, list.Count); for (int num9 = num7; num9 < num8; num9++) { UpgradeInstance val2 = list[num9]; if (val2 != null && !((Object)(object)val2.Upgrade == (Object)null)) { try { PlayerData.UnequipFromAll(val2); } catch { } val2.Destroy(); num++; } } } } try { foreach (KeyValuePair item5 in dictionary) { PlayerData.Instance.AddResource(item5.Key, item5.Value, true); } } catch (Exception ex2) { SparrohPlugin.Logger.LogError((object)("ScrapNonFavoriteUpgrades: Failed to add resources: " + ex2.Message)); } if (num > 0) { UndoPatches.EndBatch(); try { wasScrappingSkins = flag; RefreshOpenWindows(); } catch (Exception ex3) { SparrohPlugin.Logger.LogError((object)("ScrapNonFavoriteUpgrades: Failed to refresh windows: " + ex3.Message)); } } else { UndoPatches.CancelBatch(); } isScrapping = false; } public static void TryScrapNonFavoriteUpgrades(MonoBehaviour owner) { GearDetailsWindow val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return; } IUpgradable upgradablePrefab = val.UpgradablePrefab; if (upgradablePrefab == null) { return; } List obj = (((bool)AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").GetValue(val)) ? PlayerData.GetAllSkins(upgradablePrefab, true) : PlayerData.GetAllUpgrades(upgradablePrefab, true)); bool flag = false; foreach (UpgradeInfo item in obj) { if (item?.Instances != null && item.Instances.Any((UpgradeInstance inst) => inst != null && !IsFavorite(inst))) { flag = true; break; } } if (flag) { owner.StartCoroutine(ScrapNonFavoriteUpgrades()); } } private static void RefreshOpenWindows() { if (!((Object)(object)Menu.Instance != (Object)null) || !Menu.Instance.IsOpen) { return; } Window top = Menu.Instance.WindowSystem.GetTop(); if (!((Object)(object)top != (Object)null)) { return; } top.OnOpen(Menu.Instance.WindowSystem); if (wasScrappingSkins) { GearDetailsWindow val = (GearDetailsWindow)(object)((top is GearDetailsWindow) ? top : null); if ((Object)(object)val != (Object)null) { AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").SetValue(val, true); } wasScrappingSkins = false; } } } public class Patches { private static HashSet toggledThisSession = new HashSet(); private static void AddScrapButton(GearDetailsWindow window) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016d: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)window).transform.Find("ModScrapButtonMarked"); if ((Object)(object)val != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } Transform val2 = ((Component)window).transform.Find("ModScrapButtonNonFavorite"); if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val2).gameObject); } RectTransform component = ((Component)((Component)window).transform).GetComponent(); GameObject val3 = new GameObject("ModScrapButtonMarked"); val3.transform.SetParent(((Component)window).transform, false); RectTransform val4 = val3.AddComponent(); val4.sizeDelta = new Vector2(200f, 50f); val4.anchorMin = new Vector2(1f, 0f); val4.anchorMax = new Vector2(1f, 0f); val4.pivot = new Vector2(1f, 0f); Rect rect = component.rect; val4.anchoredPosition = new Vector2((0f - ((Rect)(ref rect)).width) * 0.25f, 10f); Image obj = val3.AddComponent(); ((Graphic)obj).color = Color.gray; ((Graphic)obj).raycastTarget = true; Button obj2 = val3.AddComponent