Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MoreShopItems Updated v3.3.0
MoreShopItems.dll
Decompiled 2 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using MoreShopItems.Compatability; using MoreShopItems.Config; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("MoreShopItems")] [assembly: AssemblyDescription("More Shop Items Mod for R.E.P.O.! Originally developed by InfusedGalaxy, updated by Jettcodey.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("InfusedGalaxy, Jettcodey")] [assembly: AssemblyProduct("MoreShopItems")] [assembly: AssemblyCopyright("")] [assembly: ComVisible(false)] [assembly: Guid("b52829e7-88b6-4158-ba1b-23566c7cf06b")] [assembly: AssemblyFileVersion("3.3.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.3.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MoreShopItems { [BepInPlugin("Jettcodey.MoreShopItems", "More Shop Items", "3.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static GameObject? CustomItemShelf; private readonly Harmony _harmony = new Harmony("Jettcodey.MoreShopItems"); internal Dictionary<string, ConfigEntry<int>> intConfigEntries = new Dictionary<string, ConfigEntry<int>>(); internal Dictionary<string, ConfigEntry<bool>> boolConfigEntries = new Dictionary<string, ConfigEntry<bool>>(); internal static Plugin? Instance { get; private set; } internal static ManualLogSource? Logger { get; private set; } private void Awake() { Instance = this; ((Component)this).gameObject.AddComponent<MoreShopItemsSplash>(); Logger = ((BaseUnityPlugin)this).Logger; LoadConfig(); AssetBundle bundle = LoadAssetBundle("moreshopitems_assets.file"); CustomItemShelf = LoadAssetFromBundle(bundle, "custom_soda_shelf"); if ((Object)(object)CustomItemShelf == (Object)null) { Logger.LogError((object)"Failed to load CustomItemShelf from asset bundle."); return; } _harmony.PatchAll(typeof(ShopManagerPatch)); _harmony.PatchAll(typeof(StatsManagerPatch)); _harmony.PatchAll(typeof(PunManagerPatch)); _harmony.PatchAll(typeof(PlayerControllerPatch)); Logger.LogInfo((object)"Plugin More Shop Items v3.3.0 loaded successfully."); } private AssetBundle LoadAssetBundle(string filename) { Plugin? instance = Instance; string path = Path.GetDirectoryName((instance != null) ? ((BaseUnityPlugin)instance).Info.Location : null) ?? ""; string text = Path.Combine(path, filename); if (!File.Exists(text)) { Logger.LogError((object)("Asset bundle not found at " + text)); return null; } AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { Logger.LogError((object)("Failed to load asset bundle from " + text)); } return val; } private GameObject LoadAssetFromBundle(AssetBundle bundle, string assetName) { if ((Object)(object)bundle == (Object)null) { return null; } GameObject val = bundle.LoadAsset<GameObject>(assetName); if ((Object)(object)val == (Object)null) { Logger.LogError((object)("Asset '" + assetName + "' not found in bundle.")); } return val; } private void LoadConfig() { string[] configDescriptions = ConfigEntries.GetConfigDescriptions(); intConfigEntries.Add("Max Upgrades In Shop", ConfigHelper.CreateConfig("Upgrades", "Max Upgrades In Shop", 5, configDescriptions[0], -1, 50)); intConfigEntries.Add("Max Upgrade Purchase Amount", ConfigHelper.CreateConfig("Upgrades", "Max Upgrade Purchase Amount", 0, configDescriptions[1], 0, 70)); intConfigEntries.Add("Max Melee Weapons In Shop", ConfigHelper.CreateConfig("Weapons", "Max Melee Weapons In Shop", 5, configDescriptions[2], -1, 25)); intConfigEntries.Add("Max Melee Weapon Purchase Amount", ConfigHelper.CreateConfig("Weapons", "Max Melee Weapon Purchase Amount", 0, configDescriptions[3], 0, 20)); intConfigEntries.Add("Max Guns In Shop", ConfigHelper.CreateConfig("Weapons", "Max Guns In Shop", 5, configDescriptions[4], -1, 20)); intConfigEntries.Add("Max Gun Purchase Amount", ConfigHelper.CreateConfig("Weapons", "Max Gun Purchase Amount", 0, configDescriptions[5], 0, 20)); intConfigEntries.Add("Max Grenades In Shop", ConfigHelper.CreateConfig("Weapons", "Max Grenades In Shop", 5, configDescriptions[6], -1, 20)); intConfigEntries.Add("Max Grenade Purchase Amount", ConfigHelper.CreateConfig("Weapons", "Max Grenade Purchase Amount", 0, configDescriptions[7], 0, 20)); intConfigEntries.Add("Max Mines In Shop", ConfigHelper.CreateConfig("Weapons", "Max Mines In Shop", 5, configDescriptions[8], -1, 20)); intConfigEntries.Add("Max Mine Purchase Amount", ConfigHelper.CreateConfig("Weapons", "Max Mine Purchase Amount", 0, configDescriptions[9], 0, 20)); intConfigEntries.Add("Max Health-Packs In Shop", ConfigHelper.CreateConfig("Health-Packs", "Max Health-Packs In Shop", 15, configDescriptions[10], -1, 40)); intConfigEntries.Add("Max Health-Pack Purchase Amount", ConfigHelper.CreateConfig("Health-Packs", "Max Health-Pack Purchase Amount", 0, configDescriptions[11], 0, 20)); intConfigEntries.Add("Max Drones In Shop", ConfigHelper.CreateConfig("Utilities", "Max Drones In Shop", 5, configDescriptions[12], -1, 20)); intConfigEntries.Add("Max Drone Purchase Amount", ConfigHelper.CreateConfig("Utilities", "Max Drone Purchase Amount", 0, configDescriptions[13], 0, 20)); intConfigEntries.Add("Max Orbs In Shop", ConfigHelper.CreateConfig("Utilities", "Max Orbs In Shop", 5, configDescriptions[14], -1, 20)); intConfigEntries.Add("Max Orb Purchase Amount", ConfigHelper.CreateConfig("Utilities", "Max Orb Purchase Amount", 0, configDescriptions[15], 0, 20)); intConfigEntries.Add("Max Crystals In Shop", ConfigHelper.CreateConfig("Utilities", "Max Crystals In Shop", 10, configDescriptions[16], -1, 20)); intConfigEntries.Add("Max Crystal Purchase Amount", ConfigHelper.CreateConfig("Utilities", "Max Crystal Purchase Amount", 0, configDescriptions[17], 0, 20)); intConfigEntries.Add("Max Trackers In Shop", ConfigHelper.CreateConfig("Utilities", "Max Trackers In Shop", 5, configDescriptions[18], -1, 20)); intConfigEntries.Add("Max Tracker Purchase Amount", ConfigHelper.CreateConfig("Utilities", "Max Tracker Purchase Amount", 0, configDescriptions[19], 0, 20)); intConfigEntries.Add("Max Carts In Shop", ConfigHelper.CreateConfig("Carts", "Max Carts In Shop", 2, configDescriptions[24], -1, 4)); intConfigEntries.Add("Max Cart Purchase Amount", ConfigHelper.CreateConfig("Carts", "Max Cart Purchase Amount", 0, configDescriptions[25], 0, 20)); intConfigEntries.Add("Max Pocket Carts In Shop", ConfigHelper.CreateConfig("Carts", "Max Pocket Carts In Shop", 2, configDescriptions[26], -1, 4)); intConfigEntries.Add("Max Pocket Cart Purchase Amount", ConfigHelper.CreateConfig("Carts", "Max Pocket Cart Purchase Amount", 0, configDescriptions[27], 0, 20)); intConfigEntries.Add("Max Tools In Shop", ConfigHelper.CreateConfig("Tools", "Max Tools In Shop", 2, configDescriptions[28], -1, 20)); intConfigEntries.Add("Max Tool Purchase Amount", ConfigHelper.CreateConfig("Tools", "Max Tool Purchase Amount", 0, configDescriptions[29], 0, 20)); intConfigEntries.Add("Max Additional Shelves In Shop", ConfigHelper.CreateConfig("General", "Max Additional Shelves In Shop", 2, configDescriptions[23], 0, 2)); boolConfigEntries.Add("Override Modded Items", ConfigHelper.CreateConfig("General", "Override Modded Items", value: true, configDescriptions[20], -1, -1)); boolConfigEntries.Add("Override Single-Use Upgrades", ConfigHelper.CreateConfig("General", "Override Single-Use Upgrades", value: false, configDescriptions[21], -1, -1)); boolConfigEntries.Add("Spawn Additional Shelving", ConfigHelper.CreateConfig("General", "Spawn Additional Shelving", value: true, configDescriptions[22], -1, -1)); boolConfigEntries.Add("Item Spawn Logs", ConfigHelper.CreateConfig("Dev General", "Item Spawn Logs", value: false, configDescriptions[30], -1, -1)); boolConfigEntries.Add("No Shop Damage", ConfigHelper.CreateConfig("General", "No Shop Damage", value: false, configDescriptions[31], -1, -1)); } } public class MoreShopItemsSplash : MonoBehaviour { [HarmonyPatch(typeof(SplashScreen), "SkipLogic")] private static class SplashScreen_SkipLogic_Patch { private static bool Prefix() { return !BlockSplashSkip; } } public static bool BlockSplashSkip = false; private Harmony _patcher; private static readonly string[] IncompatibleGuids = new string[5] { "Traktool.SharedUpgrades", "Empress.SharedUpgradesCompat", "Omniscye.SharedUpgradesHelper", "Janson.BaddiesTeamUpgrades", "EvilCheetah.REPO.TeamBoosters" }; private bool incompatibilityDetected; private bool overlayShown; private GameObject overlayRoot; private float previousTimeScale = 1f; private bool previousCursorVisible = false; private CursorLockMode previousCursorLockState = (CursorLockMode)1; private void Awake() { Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private void Start() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown incompatibilityDetected = IncompatibleGuids.Any((string g) => Chainloader.PluginInfos.ContainsKey(g)); if (!incompatibilityDetected) { Object.Destroy((Object)(object)this); return; } if (Chainloader.PluginInfos.ContainsKey("Empress.SkipToMainMenu")) { Plugin.Logger.LogInfo((object)"Detected 'Empress.SkipToMainMenu'."); incompatibilityDetected = true; Plugin.Logger.LogInfo((object)"Applying patch for 'Empress.SkipToMainMenu' to show Incompatibility Warning."); PatchModAConflict(); } Plugin.Logger.LogInfo((object)("Incompatible plugin(s) detected: " + string.Join(", ", IncompatibleGuids.Where((string g) => Chainloader.PluginInfos.ContainsKey(g))) + ".")); _patcher = new Harmony("MoreShopItems.SplashBlock"); _patcher.PatchAll(); BlockSplashSkip = true; } private void Update() { if (!incompatibilityDetected || overlayShown) { return; } try { SplashScreenUI instance = SplashScreenUI.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.warningTransform != (Object)null && ((Component)instance.warningTransform).gameObject.activeInHierarchy) { ShowOverlay(); } } catch (Exception ex) { Plugin.Logger.LogError((object)("MoreShopItemsSplash Update error: " + ex)); Object.Destroy((Object)(object)this); } } private void PatchModAConflict() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("Empress.SkipToMainMenu.SkipToMainMenu"); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "Update", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo methodInfo2 = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => BlockModAUpdate())); Harmony val = new Harmony("MoreShopItems.ModAFix"); val.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Failed to patch SkipToMainMenu: {arg}"); Object.Destroy((Object)(object)this); } } private static bool BlockModAUpdate() { return !BlockSplashSkip; } private void ShowOverlay() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: 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_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Unknown result type (might be due to invalid IL or missing references) //IL_0561: Expected O, but got Unknown //IL_0570: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Expected O, but got Unknown //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_0593: Expected O, but got Unknown BlockSplashSkip = true; overlayShown = true; previousTimeScale = Time.timeScale; previousCursorVisible = Cursor.visible; previousCursorLockState = Cursor.lockState; Time.timeScale = 0f; Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; overlayRoot = new GameObject("MoreShopItems_IncompatibilityOverlay", new Type[1] { typeof(RectTransform) }); Object.DontDestroyOnLoad((Object)(object)overlayRoot); Canvas val = overlayRoot.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 10000; CanvasScaler val2 = overlayRoot.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.matchWidthOrHeight = 0.5f; overlayRoot.AddComponent<GraphicRaycaster>(); GameObject val3 = CreateUIObject("Background", overlayRoot.transform); Image val4 = val3.AddComponent<Image>(); ((Graphic)val4).color = new Color(0f, 0f, 0f, 0.85f); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; GameObject val5 = CreateUIObject("Panel", overlayRoot.transform); Image val6 = val5.AddComponent<Image>(); ((Graphic)val6).color = new Color(0.51f, 0.1f, 0.1f, 0.95f); RectTransform component2 = val5.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.1f, 0.1f); component2.anchorMax = new Vector2(0.9f, 0.85f); component2.pivot = new Vector2(0.5f, 0.5f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = new Vector2(0f, 0f); ((Transform)component2).localScale = Vector3.one; GameObject val7 = CreateText("Title", 38, (FontStyle)1, val5.transform); RectTransform component3 = val7.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0.05f, 0.86f); component3.anchorMax = new Vector2(0.95f, 0.97f); component3.offsetMin = Vector2.zero; component3.offsetMax = Vector2.zero; val7.GetComponent<Text>().alignment = (TextAnchor)4; val7.GetComponent<Text>().text = "MoreShopItems Mod Conflict Detected!\nPLEASE READ CAREFULLY"; GameObject val8 = CreateText("Message", 28, (FontStyle)0, val5.transform); RectTransform component4 = val8.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0.05f, 0.38f); component4.anchorMax = new Vector2(0.95f, 0.86f); component4.offsetMin = Vector2.zero; component4.offsetMax = Vector2.zero; Text component5 = val8.GetComponent<Text>(); component5.alignment = (TextAnchor)1; component5.horizontalOverflow = (HorizontalWrapMode)0; component5.verticalOverflow = (VerticalWrapMode)1; component5.text = "Detected installed mod(s): " + string.Join(", ", IncompatibleGuids.Where((string g) => Chainloader.PluginInfos.ContainsKey(g))) + "\n\nUsing these mods together with MoreShopItems CAN and WILL cause serious issues, including:\n- Getting stuck on the loading screen\n- Player upgrades not applying correctly or disappearing\n- Unpredictable Game behavior and Game instability\n- Corrupted Save files and Game crashes\n\nYou MUST disable / uninstall the listed mods above to use MoreShopItems without issues!\nCompatible and recommended mods to use with MoreShopItems instead:\n- BetterTeamUpgrades by MrByteSized\n- SharedUpgradesPlus by Vippy\n\nChoose how you want to proceed:"; GameObject val9 = CreateUIObject("Buttons", val5.transform); RectTransform component6 = val9.GetComponent<RectTransform>(); component6.anchorMin = new Vector2(0.05f, 0.08f); component6.anchorMax = new Vector2(0.95f, 0.26f); component6.offsetMin = Vector2.zero; component6.offsetMax = Vector2.zero; ((Transform)component6).localScale = Vector3.one; Button val10 = CreateButton("DisableThisPlugin", val9.transform); Button val11 = CreateButton("ContinueAnyway", val9.transform); Button val12 = CreateButton("QuitGame", val9.transform); RectTransform component7 = ((Component)val10).GetComponent<RectTransform>(); RectTransform component8 = ((Component)val11).GetComponent<RectTransform>(); RectTransform component9 = ((Component)val12).GetComponent<RectTransform>(); component7.anchorMin = new Vector2(0.02f, 0.1f); component7.anchorMax = new Vector2(0.32f, 0.9f); component7.offsetMin = Vector2.zero; component7.offsetMax = Vector2.zero; component8.anchorMin = new Vector2(0.34f, 0.1f); component8.anchorMax = new Vector2(0.66f, 0.9f); component8.offsetMin = Vector2.zero; component8.offsetMax = Vector2.zero; component9.anchorMin = new Vector2(0.68f, 0.1f); component9.anchorMax = new Vector2(0.98f, 0.9f); component9.offsetMin = Vector2.zero; component9.offsetMax = Vector2.zero; ((Component)val10).GetComponentInChildren<Text>().text = "Disable MoreShopItems"; ((Component)val11).GetComponentInChildren<Text>().text = "Continue anyway"; ((Component)val12).GetComponentInChildren<Text>().text = "Quit Game"; ((UnityEvent)val10.onClick).AddListener((UnityAction)delegate { Plugin.Logger.LogWarning((object)"User chose to disable MoreShopItems due to incompatibility."); TryUnpatchAndDisablePlugin(); CloseOverlay(); }); ((UnityEvent)val11.onClick).AddListener((UnityAction)delegate { Plugin.Logger.LogWarning((object)"User chose to continue with potential incompatibility."); CloseOverlay(); }); ((UnityEvent)val12.onClick).AddListener((UnityAction)delegate { Plugin.Logger.LogWarning((object)"User chose to quit because of incompatibility."); CloseOverlay(); Application.Quit(); }); } private void TryUnpatchAndDisablePlugin() { try { Harmony.UnpatchID("MoreShopItems"); } catch (Exception ex) { Plugin.Logger.LogError((object)("Error while unpatching Harmony patches: " + ex)); } try { if ((Object)(object)Plugin.Instance != (Object)null) { Object.Destroy((Object)(object)Plugin.Instance); Plugin.Logger.LogInfo((object)"Plugin component destroyed."); } else { Plugin.Logger.LogWarning((object)"Plugin instance was null when attempting to disable."); } } catch (Exception ex2) { Plugin.Logger.LogError((object)("Error while destroying plugin instance: " + ex2)); } } private void CloseOverlay() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) BlockSplashSkip = false; if ((Object)(object)overlayRoot != (Object)null) { Object.Destroy((Object)(object)overlayRoot); overlayRoot = null; } Time.timeScale = previousTimeScale; Cursor.visible = previousCursorVisible; Cursor.lockState = previousCursorLockState; Object.Destroy((Object)(object)this); } private GameObject CreateUIObject(string name, Transform parent) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).localScale = Vector3.one; return val; } private GameObject CreateText(string name, int fontSize, FontStyle style, Transform parent) { //IL_002c: 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_0059: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateUIObject(name, parent); Text val2 = val.AddComponent<Text>(); val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val2.fontSize = fontSize; val2.fontStyle = style; ((Graphic)val2).color = Color.white; val2.alignment = (TextAnchor)4; RectTransform component = val.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(600f, 40f); return val; } private Button CreateButton(string name, Transform parent) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateUIObject(name, parent); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = new Color(0.22f, 0.22f, 0.22f, 0.95f); Button val3 = val.AddComponent<Button>(); ((Selectable)val3).transition = (Transition)1; ColorBlock colors = ((Selectable)val3).colors; ((ColorBlock)(ref colors)).normalColor = new Color(0.22f, 0.22f, 0.22f, 0.95f); ((ColorBlock)(ref colors)).highlightedColor = new Color(0.12f, 0.12f, 0.12f, 0.95f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.17f, 0.17f, 0.17f, 0.95f); ((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).highlightedColor; ((ColorBlock)(ref colors)).disabledColor = new Color(0.12f, 0.12f, 0.12f, 0.5f); ((ColorBlock)(ref colors)).colorMultiplier = 1f; ((ColorBlock)(ref colors)).fadeDuration = 0.08f; ((Selectable)val3).colors = colors; RectTransform component = val.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(200f, 56f); GameObject val4 = CreateText("Label", 28, (FontStyle)0, val.transform); RectTransform component2 = val4.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 0f); component2.anchorMax = new Vector2(1f, 1f); component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; return val3; } private void OnDestroy() { if (Time.timeScale == 0f) { Time.timeScale = 1f; } Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } private void LateUpdate() { if (overlayShown && (Object)(object)overlayRoot != (Object)null && Input.GetKeyDown((KeyCode)27)) { Plugin.Logger.LogInfo((object)"Escape pressed (continue anyway), closing MoreShopItems incompatibility overlay."); CloseOverlay(); } } } public static class MultiplayerHandler { public const string ModCheckKey = "Jettcodey_MoreShopItems 3.3.0"; public static bool IsModEnabled() { if (!SemiFunc.IsMultiplayer()) { return true; } if (PhotonNetwork.CurrentRoom == null) { return false; } if (PhotonNetwork.IsMasterClient) { return true; } if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"Jettcodey_MoreShopItems 3.3.0", out object value)) { return (bool)value; } return false; } public static void SetModActive() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0030: Expected O, but got Unknown if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null) { Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"Jettcodey_MoreShopItems 3.3.0", (object)true); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); Plugin.Logger.LogInfo((object)"Mod version 3.3.0 presence announced to room for Clients!"); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Jettcodey.MoreShopItems"; public const string PLUGIN_NAME = "More Shop Items"; public const string PLUGIN_VERSION = "3.3.0"; } [HarmonyPatch] public class NoShopDamage { [HarmonyPrefix] [HarmonyPatch(typeof(PlayerHealth), "Hurt")] public static bool HurtPrefix() { if (Plugin.Instance.boolConfigEntries["No Shop Damage"].Value && (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelShop) { if (ChatManager.instance.betrayalActive) { return true; } return false; } return true; } } [HarmonyPatch(typeof(PunManager))] internal static class PunManagerPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPostfix() { if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { MultiplayerHandler.SetModActive(); } } [HarmonyPrefix] [HarmonyPatch("TruckPopulateItemVolumes")] private static void RemoveNullValues() { if ((Object)(object)ItemManager.instance != (Object)null && (SemiFunc.IsMasterClient() || !SemiFunc.IsMultiplayer())) { Predicate<ItemVolume> match = (ItemVolume volume) => (Object)(object)volume == (Object)null; ItemManager.instance.itemVolumes.RemoveAll(match); } } } [HarmonyPatch(typeof(PlayerController))] internal static class PlayerControllerPatch { [CompilerGenerated] private sealed class <ClientCheckRoutine>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private int <retries>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ClientCheckRoutine>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <retries>5__1 = 5; break; case 1: <>1__state = -1; <retries>5__1--; break; } if (<retries>5__1 > 0) { if (MultiplayerHandler.IsModEnabled()) { Plugin.Logger.LogInfo((object)"Host Player has the Mod Enabled, Mod is active!"); return false; } <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 1; return true; } Plugin.Logger.LogWarning((object)"Host does NOT have the mod Enabled or is using a different Version, Mod is disabled!"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePrefix() { if (SemiFunc.IsMultiplayer() && !SemiFunc.IsMasterClient()) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ClientCheckRoutine()); } } [IteratorStateMachine(typeof(<ClientCheckRoutine>d__1))] public static IEnumerator ClientCheckRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ClientCheckRoutine>d__1(0); } } internal class ShelfEventListener : MonoBehaviourPunCallbacks, IOnEventCallback { private static bool _created; private static readonly HashSet<string> spawnedShelves = new HashSet<string>(); public static void Ensure() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!_created) { _created = true; GameObject val = new GameObject("MoreShopItems_ShelfEventListener"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<ShelfEventListener>(); Plugin.Logger.LogInfo((object)"ShelfEventListener created!"); } } private void OnEnable() { PhotonNetwork.AddCallbackTarget((object)this); } private void OnDisable() { PhotonNetwork.RemoveCallbackTarget((object)this); } public override void OnJoinedRoom() { lock (spawnedShelves) { spawnedShelves.Clear(); } Plugin.Logger.LogInfo((object)"[ShelfEventListener] OnJoinedRoom: cleared spawned shelf registry"); } public override void OnLeftRoom() { lock (spawnedShelves) { spawnedShelves.Clear(); } Plugin.Logger.LogInfo((object)"[ShelfEventListener] OnLeftRoom: cleared spawned shelf registry"); } public void OnEvent(EventData photonEvent) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_00dc: Unknown result type (might be due to invalid IL or missing references) if (photonEvent.Code != 155 || !(photonEvent.CustomData is object[] array) || array.Length < 5) { return; } string text = array[0] as string; Vector3 val = (Vector3)array[1]; Quaternion val2 = (Quaternion)array[2]; string text2 = array[3] as string; string text3 = array[4] as string; if (!string.IsNullOrEmpty(text) && !spawnedShelves.Contains(text)) { GameObject obj = GameObject.Find(text2); Transform val3 = ((obj != null) ? obj.transform : null); if ((Object)(object)val3 == (Object)null) { Plugin.Logger.LogWarning((object)("[ShelfEventListener] Parent " + text2 + " not found for shelf " + text3)); return; } Object.Instantiate<GameObject>(Plugin.CustomItemShelf, val, val2, val3); spawnedShelves.Add(text); Plugin.Logger.LogInfo((object)("[ShelfEventListener] Spawned shelf " + text3 + " for client via event")); } } } internal static class ShelfEvents { public const byte EV_SPAWN_SHELF = 155; public static void RaiseSpawnShelf(string shelfID, Vector3 pos, Quaternion rot, string parentName, string placeholder) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom) { Plugin.Logger.LogWarning((object)("[ShelfEvents] Not in room - cannot raise event for shelf " + placeholder)); return; } object[] array = new object[5] { shelfID, pos, rot, parentName, placeholder }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; SendOptions val2 = default(SendOptions); ((SendOptions)(ref val2)).Reliability = true; SendOptions val3 = val2; PhotonNetwork.RaiseEvent((byte)155, (object)array, val, val3); Plugin.Logger.LogInfo((object)("[ShelfEvents] Master raised EV_SPAWN_SHELF for " + placeholder)); } } [HarmonyPatch(typeof(ShopManager))] internal static class ShopManagerPatch { [HarmonyPatch(typeof(ShopManager), "UpgradeValueGet")] public static class ShopManager_UpgradeValueGet_Patch { [HarmonyPrefix] public static bool Prefix(ref float __result, float _value, Item item) { ShopManager instance = ShopManager.instance; if ((Object)(object)instance == (Object)null) { return true; } int num = Mathf.Max(1, GameDirector.instance.PlayerList.Count); float num2 = 0.1f * (float)(num - 1); float num3 = Mathf.Min(0.5f, num2); float num4 = _value; num4 -= num4 * num3; if ((Object)(object)item != (Object)null) { num4 += num4 * instance.upgradeValueIncrease * (float)StatsManager.instance.GetItemsUpgradesPurchased(((Object)item).name); } num4 = Mathf.Ceil(num4); __result = Mathf.Max(num4, 1f); return false; } } [HarmonyPatch(typeof(ShopManager), "HealthPackValueGet")] public static class ShopManager_HealthPackValueGet_Patch { [HarmonyPrefix] public static bool Prefix(ref float __result, float _value) { ShopManager instance = ShopManager.instance; if ((Object)(object)instance == (Object)null) { return true; } int num = Mathf.Max(1, GameDirector.instance.PlayerList.Count); float num2 = 0.1f * (float)(num - 1); float num3 = Mathf.Min(0.5f, num2); float num4 = _value; int num5 = Mathf.Min(RunManager.instance.levelsCompleted, 15); num4 -= num4 * num3; num4 += num4 * instance.healthPackValueIncrease * (float)num5; num4 = Mathf.Ceil(num4); __result = Mathf.Max(num4, 1f); return false; } } [HarmonyPatch(typeof(ItemAttributes), "GetValue")] public static class ItemAttributes_GetValue_Patch { [HarmonyPrefix] public static bool Prefix(ItemAttributes __instance) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Invalid comparison between Unknown and I4 //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Invalid comparison between Unknown and I4 //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Invalid comparison between Unknown and I4 if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient) { return true; } Type typeFromHandle = typeof(ItemAttributes); FieldInfo fieldInfo = AccessTools.Field(typeFromHandle, "itemValueMin"); FieldInfo fieldInfo2 = AccessTools.Field(typeFromHandle, "itemValueMax"); if (fieldInfo == null || fieldInfo2 == null) { return true; } float num = (float)fieldInfo.GetValue(__instance); float num2 = (float)fieldInfo2.GetValue(__instance); float num3 = Random.Range(num, num2) * ShopManager.instance.itemValueMultiplier; if (num3 < 1000f) { num3 = 1000f; } float num4 = Mathf.Ceil(num3 / 1000f); if ((int)__instance.itemType == 3) { num4 = ShopManager.instance.UpgradeValueGet(num4, __instance.item); } else if ((int)__instance.itemType == 8) { num4 = ShopManager.instance.HealthPackValueGet(num4); } else if ((int)__instance.itemType == 5) { num4 = ShopManager.instance.CrystalValueGet(num4); } num4 = Mathf.Max(num4, 1f); int num5 = (int)num4; FieldInfo fieldInfo3 = AccessTools.Field(typeFromHandle, "value"); if (fieldInfo3 != null) { fieldInfo3.SetValue(__instance, num5); } else { __instance.value = num5; } if (GameManager.Multiplayer()) { __instance.photonView.RPC("GetValueRPC", (RpcTarget)1, new object[1] { num5 }); } return false; } } internal static class ShelfSpawner { public static GameObject? Spawn(Vector3 pos, Quaternion rot, Transform parentTransform, string placeholderName) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) try { if (!SemiFunc.IsMultiplayer()) { if ((Object)(object)Plugin.CustomItemShelf == (Object)null) { Plugin.Logger.LogError((object)"CustomItemShelf is null. Cannot spawn shelf."); return null; } if ((Object)(object)parentTransform != (Object)null) { return Object.Instantiate<GameObject>(Plugin.CustomItemShelf, pos, rot, parentTransform); } return Object.Instantiate<GameObject>(Plugin.CustomItemShelf, pos, rot); } if (SemiFunc.IsMasterClient()) { if ((Object)(object)Plugin.CustomItemShelf == (Object)null) { Plugin.Logger.LogError((object)"CustomItemShelf is null on host. Cannot spawn shelf."); return null; } string text = Guid.NewGuid().ToString("N"); GameObject val = Object.Instantiate<GameObject>(Plugin.CustomItemShelf, pos, rot); ((Object)val).name = "MoreShopShelf_" + text; if ((Object)(object)parentTransform != (Object)null) { val.transform.SetParent(parentTransform, true); } if (!string.IsNullOrEmpty(placeholderName)) { GameObject val2 = GameObject.Find(placeholderName); if ((Object)(object)val2 != (Object)null) { val2.SetActive(false); } } string parentName = (((Object)(object)parentTransform != (Object)null) ? ((Object)((Component)parentTransform).gameObject).name : string.Empty); try { ShelfEvents.RaiseSpawnShelf(text, pos, rot, parentName, placeholderName ?? string.Empty); } catch (Exception ex) { Plugin.Logger.LogError((object)("ShelfSpawner: RaiseSpawnShelf failed: " + ex)); } return val; } return null; } catch (Exception ex2) { Plugin.Logger.LogError((object)("ShelfSpawner.Spawn exception: " + ex2)); return null; } } } private static readonly FieldRef<ShopManager, int> itemSpawnTargetAmount_ref = AccessTools.FieldRefAccess<ShopManager, int>("itemSpawnTargetAmount"); private static readonly FieldRef<ShopManager, int> itemConsumablesAmount_ref = AccessTools.FieldRefAccess<ShopManager, int>("itemConsumablesAmount"); private static readonly FieldRef<ShopManager, int> itemUpgradesAmount_ref = AccessTools.FieldRefAccess<ShopManager, int>("itemUpgradesAmount"); private static readonly FieldRef<ShopManager, int> itemHealthPacksAmount_ref = AccessTools.FieldRefAccess<ShopManager, int>("itemHealthPacksAmount"); private static GameObject? shelf; internal static bool isMoreUpgrades = false; private static void SetItemValues(Item item, int maxInShop, int maxPurchaseAmount) { item.maxAmountInShop = maxInShop; item.maxAmount = maxInShop; item.maxPurchase = maxPurchaseAmount > 0; item.maxPurchaseAmount = maxPurchaseAmount; if (Plugin.Instance.boolConfigEntries["Item Spawn Logs"].Value) { Plugin.Logger.LogInfo((object)$"Set values for {((Object)item).name}: maxInShop={maxInShop}, maxPurchase={item.maxPurchase}, maxPurchaseAmount={maxPurchaseAmount}"); } } [HarmonyPrefix] [HarmonyPatch("ShopInitialize")] private static void AdjustItems() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Invalid comparison between Unknown and I4 if (!(RunManager.instance.levelCurrent.ResourcePath == "Shop") || !((Object)(object)StatsManager.instance != (Object)null) || (!SemiFunc.IsMasterClient() && SemiFunc.IsMultiplayer())) { return; } Dictionary<string, ConfigEntry<int>> intConfigEntries = Plugin.Instance.intConfigEntries; Dictionary<string, ConfigEntry<bool>> boolConfigEntries = Plugin.Instance.boolConfigEntries; Plugin.Logger.LogInfo((object)("Override modded items = " + boolConfigEntries["Override Modded Items"].Value)); foreach (Item value4 in StatsManager.instance.itemDictionary.Values) { if (!ItemConfigMapper.Map.TryGetValue(value4.itemType, out (string, string, int) value)) { continue; } int value2 = intConfigEntries[value.Item1].Value; int value3 = intConfigEntries[value.Item2].Value; if (value2 == -1) { continue; } value2 += value.Item3; bool flag = (int)value4.itemType == 3; if (boolConfigEntries["Override Modded Items"].Value) { if (flag && boolConfigEntries["Override Single-Use Upgrades"].Value) { SetItemValues(value4, value2, value3); } else if (flag && !value4.maxPurchase) { SetItemValues(value4, value2, value3); } else if (!flag) { SetItemValues(value4, value2, value3); } } else if (((!MoreUpgradesMOD.isLoaded() && !NikkisUpgradesMOD.isLoaded()) || !((Object)value4).name.Contains("Modded")) && !(VanillaUpgradesMOD.isLoaded() && flag)) { if (flag && boolConfigEntries["Override Single-Use Upgrades"].Value) { SetItemValues(value4, value2, value3); } else if (flag && !value4.maxPurchase) { SetItemValues(value4, value2, value3); } else if (!flag) { SetItemValues(value4, value2, value3); } } } } [HarmonyPrefix] [HarmonyPatch(typeof(ShopManager), "GetAllItemsFromStatsManager")] private static void Prefix_GetAllItemsFromStatsManager() { AdjustItems(); } [PunRPC] public static void SetParent(Transform parent, GameObject gameObj) { gameObj.transform.SetParent(parent); } [HarmonyPrefix] [HarmonyPatch("Awake")] private static void SetValues(ShopManager __instance) { itemConsumablesAmount_ref.Invoke(__instance) = 100; itemUpgradesAmount_ref.Invoke(__instance) = 180; itemHealthPacksAmount_ref.Invoke(__instance) = 60; itemSpawnTargetAmount_ref.Invoke(__instance) = 450; } [HarmonyPostfix] [HarmonyPatch("GetAllItemsFromStatsManager")] private static void Postfix(ShopManager __instance) { __instance.itemConsumablesAmount = 100; Plugin.Logger.LogInfo((object)$"Forced itemConsumablesAmount to {__instance.itemConsumablesAmount}"); } [HarmonyPrefix] [HarmonyPatch("ShopInitialize")] private static void SpawnShelf() { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Unknown result type (might be due to invalid IL or missing references) //IL_06fe: 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_0705: Unknown result type (might be due to invalid IL or missing references) //IL_0716: Unknown result type (might be due to invalid IL or missing references) //IL_0729: Unknown result type (might be due to invalid IL or missing references) //IL_073a: Unknown result type (might be due to invalid IL or missing references) //IL_0754: Unknown result type (might be due to invalid IL or missing references) //IL_0759: Unknown result type (might be due to invalid IL or missing references) //IL_07dc: Unknown result type (might be due to invalid IL or missing references) //IL_07f0: Unknown result type (might be due to invalid IL or missing references) //IL_07f5: Unknown result type (might be due to invalid IL or missing references) //IL_07fa: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_05a4: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_0822: Unknown result type (might be due to invalid IL or missing references) //IL_0824: Unknown result type (might be due to invalid IL or missing references) //IL_0860: Unknown result type (might be due to invalid IL or missing references) //IL_0862: Unknown result type (might be due to invalid IL or missing references) //IL_08d1: Unknown result type (might be due to invalid IL or missing references) //IL_08d6: Unknown result type (might be due to invalid IL or missing references) //IL_0942: Unknown result type (might be due to invalid IL or missing references) //IL_0947: Unknown result type (might be due to invalid IL or missing references) //IL_0923: Unknown result type (might be due to invalid IL or missing references) //IL_0994: Unknown result type (might be due to invalid IL or missing references) if (!(RunManager.instance.levelCurrent.ResourcePath == "Shop") || !Plugin.Instance.boolConfigEntries["Spawn Additional Shelving"].Value) { return; } ShelfEventListener.Ensure(); int value = Plugin.Instance.intConfigEntries["Max Additional Shelves In Shop"].Value; if (value <= 0) { return; } HashSet<string> hashSet = new HashSet<string>(); int num = 0; for (int i = 0; i < value; i++) { bool flag = false; if (!hashSet.Contains("Soda")) { GameObject val = GameObject.Find("Soda Shelf"); GameObject val2 = GameObject.Find("Module Switch BOT"); if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && !val2.GetComponent<ModulePropSwitch>().ConnectedParent.activeSelf) { Vector3 position = val.transform.position; Quaternion rotation = val.transform.rotation; Transform transform = val2.transform; string placeholderName = "Soda Shelf"; if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { GameObject val3 = ShelfSpawner.Spawn(position, rotation, transform, placeholderName); if ((Object)(object)val3 != (Object)null) { SetParent(transform, val3); } } else if (!SemiFunc.IsMultiplayer()) { Object.Instantiate<GameObject>(Plugin.CustomItemShelf, position, rotation, transform); } val.SetActive(false); hashSet.Add("Soda"); num++; flag = true; } } if (flag) { continue; } if (!hashSet.Contains("Magazine")) { GameObject val4 = GameObject.Find("Module Switch (1) top"); GameObject val5 = GameObject.Find("Shop Magazine Stand (1)"); GameObject val6 = GameObject.Find("Shop Magazine Stand"); if ((Object)(object)val5 != (Object)null && (Object)(object)val4 != (Object)null && !val4.GetComponent<ModulePropSwitch>().ConnectedParent.activeSelf) { Vector3 position2 = val5.transform.position; Quaternion val7 = val5.transform.rotation * Quaternion.Euler(0f, 90f, 0f); Transform parent = val4.transform.parent; string placeholderName2 = "Shop Magazine Stand (1)"; if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { GameObject val8 = ShelfSpawner.Spawn(position2, val7, parent, placeholderName2); if ((Object)(object)val8 != (Object)null) { SetParent(parent, val8); } } else if (!SemiFunc.IsMultiplayer()) { Object.Instantiate<GameObject>(Plugin.CustomItemShelf, position2, val7, parent); } val5.SetActive(false); if ((Object)(object)val6 != (Object)null) { val6.SetActive(false); } hashSet.Add("Magazine"); num++; flag = true; } } if (flag) { continue; } if (!hashSet.Contains("Candy")) { GameObject val9 = GameObject.Find("Module Switch (2) left"); GameObject val10 = GameObject.Find("Candy Shelf"); if ((Object)(object)val9 != (Object)null && (Object)(object)val10 != (Object)null && !val9.GetComponent<ModulePropSwitch>().ConnectedParent.activeSelf) { Vector3 val11 = val9.transform.position + val9.transform.right * 0.5f - val9.transform.forward * 0.8f; Quaternion val12 = val9.transform.rotation * Quaternion.Euler(0f, 180f, 0f); Transform transform2 = val9.transform; string placeholderName3 = "Candy Shelf"; if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { GameObject val13 = ShelfSpawner.Spawn(val11, val12, transform2, placeholderName3); if ((Object)(object)val13 != (Object)null) { SetParent(transform2, val13); } } else if (!SemiFunc.IsMultiplayer()) { Object.Instantiate<GameObject>(Plugin.CustomItemShelf, val11, val12, transform2); } val10.SetActive(false); hashSet.Add("Candy"); num++; flag = true; } } if (flag) { continue; } if (!hashSet.Contains("Soda Machine")) { GameObject val14 = GameObject.Find("Soda Machine (1)"); GameObject val15 = GameObject.Find("Module Switch (1) top"); GameObject val16 = GameObject.Find("Shop Owner"); GameObject val17 = null; if ((Object)(object)val15 != (Object)null) { Transform val18 = val15.transform.Find("Connected"); if ((Object)(object)val18 != (Object)null) { Transform obj = val18.Find("Wall 01 - 1x1 - Door (3)"); val17 = ((obj != null) ? ((Component)obj).gameObject : null); } } bool flag2 = (Object)(object)val17 != (Object)null && !val17.activeSelf && (Object)(object)val16 != (Object)null && val16.activeSelf; if ((Object)(object)val14 != (Object)null && (Object)(object)val15 != (Object)null && val14.activeSelf && !flag2) { Vector3 position3 = val14.transform.position; Quaternion val19 = Quaternion.Euler(0f, 90f, 0f); Transform transform3 = val15.transform; string placeholderName4 = "Soda Machine (1)"; if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { GameObject val20 = ShelfSpawner.Spawn(position3, val19, transform3, placeholderName4); if ((Object)(object)val20 != (Object)null) { SetParent(transform3, val20); } } else if (!SemiFunc.IsMultiplayer()) { Object.Instantiate<GameObject>(Plugin.CustomItemShelf, position3, val19, transform3); } val14.SetActive(false); hashSet.Add("Soda Machine"); num++; flag = true; } else if (flag2 && (Object)(object)val14 != (Object)null) { val14.SetActive(true); } } if (flag) { continue; } if (!hashSet.Contains("cashiers shelf")) { GameObject val21 = GameObject.Find("Module Switch (2) right"); GameObject val22 = GameObject.Find("cashiers shelf"); GameObject val23 = GameObject.Find("cashiers desk"); GameObject val24 = GameObject.Find("Shop Magazine Holder"); GameObject val25 = GameObject.Find("Shop Cash register"); GameObject val26 = GameObject.Find("Shop Chair"); GameObject val27 = GameObject.Find("Shop Owner"); Transform val28 = ((val21 != null) ? val21.transform.Find("Connected") : null); if ((Object)(object)val21 != (Object)null && (Object)(object)val28 != (Object)null && !((Component)val28).gameObject.activeSelf && (Object)(object)val22 != (Object)null) { Vector3 position4 = val21.transform.position; bool flag3 = Vector3.Distance(position4, new Vector3(-7.9544f, 0f, 7.7214f)) < 0.01f; bool flag4 = Vector3.Distance(position4, new Vector3(7.9544f, 0f, 7.2786f)) < 0.01f; Vector3 position5 = val22.transform.position; if (flag3) { position5.x += 0.4f; position5.z += 1f; } else if (flag4) { position5.x -= 0.5f; position5.z -= 0.9f; } else { position5.x += 1f; position5.z -= 0.4f; } Quaternion val29 = val22.transform.rotation * Quaternion.Euler(0f, 180f, 0f); Transform transform4 = val21.transform; string placeholderName5 = "cashiers shelf"; if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { GameObject val30 = ShelfSpawner.Spawn(position5, val29, transform4, placeholderName5); if ((Object)(object)val30 != (Object)null) { SetParent(transform4, val30); } } else if (!SemiFunc.IsMultiplayer()) { Object.Instantiate<GameObject>(Plugin.CustomItemShelf, position5, val29, transform4); } val22.SetActive(false); if ((Object)(object)val24 != (Object)null) { val24.SetActive(false); } if ((Object)(object)val26 != (Object)null) { val26.SetActive(false); } if ((Object)(object)val27 != (Object)null) { val27.SetActive(false); } if ((Object)(object)val23 != (Object)null) { Vector3 position6 = val23.transform.position; if (flag3) { position6.x += 0.9f; } else if (flag4) { position6.x -= 0.9f; } else { position6.z -= 1f; } val23.transform.position = position6; } if ((Object)(object)val25 != (Object)null) { Vector3 position7 = val25.transform.position; if (flag3) { position7.x += 0.9f; } else if (flag4) { position7.x -= 0.9f; } else { position7.z -= 1f; } val25.transform.position = position7; } hashSet.Add("cashiers shelf"); num++; flag = true; } } if (!flag) { Plugin.Logger.LogInfo((object)$"No more available locations found. Stopping shelf spawn at {num} shelves."); break; } } if (num > 0) { Plugin.Logger.LogInfo((object)$"Successfully spawned {num} custom shelf/shelves!"); } } [HarmonyPostfix] [HarmonyPatch("GetAllItemVolumesInScene")] private static void LogPotentialItems(ShopManager __instance) { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Instance.boolConfigEntries["Item Spawn Logs"].Value || (Object)(object)__instance == (Object)null) { return; } Plugin.Logger.LogInfo((object)"--- Shop Initialization: Starting Item Scan ---"); Task.Delay(2000).Wait(); LogItemCollection(__instance.potentialItems, "Standard Items"); LogItemCollection(__instance.potentialItemUpgrades, "Upgrade Items"); LogItemCollection(__instance.potentialItemConsumables, "Consumables"); LogItemCollection(__instance.potentialItemHealthPacks, "Health Packs"); if (__instance.potentialSecretItems.Count > 0) { Plugin.Logger.LogInfo((object)$"Found {__instance.potentialSecretItems.Count} potential Secret Items (grouped):"); foreach (KeyValuePair<itemSecretShopType, List<Item>> potentialSecretItem in __instance.potentialSecretItems) { Plugin.Logger.LogInfo((object)$" Category: {potentialSecretItem.Key}"); LogItemCollection(potentialSecretItem.Value, "", nested: true); } } else { Plugin.Logger.LogInfo((object)"No potential Secret Items found."); } Plugin.Logger.LogInfo((object)"--- Shop Initialization: Item Scan Complete ---"); } private static void LogItemCollection(List<Item> items, string collectionName, bool nested = false) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if (items != null && items.Count > 0) { if (!string.IsNullOrEmpty(collectionName)) { Plugin.Logger.LogInfo((object)$"Found {items.Count} potential {collectionName}:"); } int num = 0; foreach (Item item in items) { if (item.itemName != null && item.itemName.Length > num) { num = item.itemName.Length; } } num += 3; { foreach (Item item2 in items) { string arg = (nested ? " - " : " - "); Plugin.Logger.LogInfo((object)$"{arg}Name: {item2.itemName.PadRight(num)}Type: {item2.itemType}"); } return; } } if (!string.IsNullOrEmpty(collectionName)) { Plugin.Logger.LogInfo((object)("No potential " + collectionName + " found.")); } } } internal class StatsManagerPatch { private static Dictionary<int, int> instancePrices = new Dictionary<int, int>(); private static Dictionary<string, List<int>> itemInstanceIds = new Dictionary<string, List<int>>(); [HarmonyPrefix] [HarmonyPatch(typeof(StatsManager), "ItemPurchase")] private static bool Prefix_ItemPurchase(string itemName, ref bool __runOriginal) { __runOriginal = true; try { if (!StatsManager.instance.itemDictionary.ContainsKey(itemName)) { return true; } Item val = StatsManager.instance.itemDictionary[itemName]; if (val.maxPurchase && val.maxPurchaseAmount > 0) { int num = StatsManager.instance.itemsPurchasedTotal[itemName]; if (num >= val.maxPurchaseAmount) { __runOriginal = false; int num2 = 0; if (itemInstanceIds.ContainsKey(itemName) && itemInstanceIds[itemName].Count > 0) { int num3 = itemInstanceIds[itemName][0]; if (instancePrices.ContainsKey(num3)) { num2 = instancePrices[num3]; instancePrices.Remove(num3); itemInstanceIds[itemName].RemoveAt(0); if (itemInstanceIds[itemName].Count == 0) { itemInstanceIds.Remove(itemName); } Plugin.Logger.LogInfo((object)$"Refunding {itemName} instance {num3} with price: {num2}"); } } if (num2 == 0) { Plugin.Logger.LogError((object)("NO PRICE FOUND for " + itemName + "! Tracking failed.")); return false; } if (num2 > 0 && StatsManager.instance.runStats.ContainsKey("currency")) { int num4 = StatsManager.instance.runStats["currency"]; StatsManager.instance.runStats["currency"] += num2; int num5 = StatsManager.instance.runStats["currency"]; Plugin.Logger.LogInfo((object)$"Refunded: {itemName} limit reached. Refunded {num2} currency ({num4} -> {num5})"); if (GameManager.Multiplayer() && PhotonNetwork.IsMasterClient) { PunManager.instance.SetRunStatSet("currency", num5); } } return false; } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in purchase check: {arg}"); } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(ShopManager), "ShoppingListItemAdd")] private static void Postfix_ShoppingListItemAdd(ItemAttributes item) { try { if ((Object)(object)item != (Object)null && (Object)(object)item.item != (Object)null) { string name = ((Object)item.item).name; int instanceID = ((Object)item).GetInstanceID(); instancePrices[instanceID] = item.value; if (!itemInstanceIds.ContainsKey(name)) { itemInstanceIds[name] = new List<int>(); } itemInstanceIds[name].Add(instanceID); Plugin.Logger.LogInfo((object)$"Added to cart: {name} instance {instanceID} for {item.value} (total instances: {itemInstanceIds[name].Count})"); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error tracking cart addition: {arg}"); } } [HarmonyPostfix] [HarmonyPatch(typeof(ShopManager), "ShoppingListItemRemove")] private static void Postfix_ShoppingListItemRemove(ItemAttributes item) { try { if (!((Object)(object)item != (Object)null) || !((Object)(object)item.item != (Object)null)) { return; } string name = ((Object)item.item).name; int instanceID = ((Object)item).GetInstanceID(); if (instancePrices.ContainsKey(instanceID)) { instancePrices.Remove(instanceID); Plugin.Logger.LogInfo((object)$"Removed instance {instanceID} from price tracking"); } if (itemInstanceIds.ContainsKey(name)) { itemInstanceIds[name].Remove(instanceID); if (itemInstanceIds[name].Count == 0) { itemInstanceIds.Remove(name); } Plugin.Logger.LogInfo((object)$"Removed from cart: {name} instance {instanceID}"); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error removing from cart: {arg}"); } } [HarmonyPostfix] [HarmonyPatch(typeof(StatsManager), "ItemPurchase")] private static void Postfix_ItemPurchase(string itemName, ref bool __runOriginal) { try { if (!__runOriginal) { return; } if (itemInstanceIds.ContainsKey(itemName) && itemInstanceIds[itemName].Count > 0) { int num = itemInstanceIds[itemName][0]; if (instancePrices.ContainsKey(num)) { int num2 = instancePrices[num]; instancePrices.Remove(num); Plugin.Logger.LogInfo((object)$"Successful purchase: {itemName} instance {num} for {num2}."); } itemInstanceIds[itemName].RemoveAt(0); if (itemInstanceIds[itemName].Count == 0) { itemInstanceIds.Remove(itemName); } } if (StatsManager.instance.itemDictionary.ContainsKey(itemName)) { Item val = StatsManager.instance.itemDictionary[itemName]; int num3 = StatsManager.instance.itemsPurchasedTotal[itemName]; Plugin.Logger.LogInfo((object)$"{itemName}: {num3}/{val.maxPurchaseAmount}"); } } catch { } } } } namespace MoreShopItems.Config { public static class ConfigEntries { private static string[] DESCRIPTIONS = new string[32] { "How many of each upgrade to spawn in the shop.", "How many upgrades you can purchase total. Set 0 to disable", "How many of each melee weapon to spawn in the shop.", "How many melee weapons you can purchase total. Set 0 to disable", "How many of each gun to spawn in the shop.", "How many guns you can purchase total. Set 0 to disable", "How many of each grenade to spawn in the shop.", "How many grenades you can purchase total. Set 0 to disable", "How many of each mine to spawn in the shop.", "How many mines you can purchase total. Set 0 to disable", "How many of each health-pack to spawn in the shop.", "How many health-packs you can purchase total. Set 0 to disable", "How many of each drone to spawn in the shop.", "How many drones you can purchase total. Set 0 to disable", "How many of each orb to spawn in the shop.", "How many orbs you can purchase total. Set 0 to disable", "How many of each crystal to spawn in the shop.", "How many crystals you can purchase total. Set 0 to disable", "How many trackers to spawn in the shop.", "How many trackers you can purchase total. Set 0 to disable", "Overrides the values (MaxAmountInShop, MaxPurchaseAmount) set by other item/upgrade mods.", "Overrides the values (MaxAmountInShop, MaxPurchaseAmount) of single-use upgrades.", "Spawns the additional shelving into the shop (set false to disable the shelf spawning).", "How many additional shelving units to spawn in the shop. Set 0 to disable.", "How many Carts to spawn in the shop.", "How many Carts you can purchase total. Set 0 to disable", "How many Pocket Carts to spawn in the shop.", "How many Pocket Carts you can purchase total. Set 0 to disable", "How many Tools to spawn in the shop.", "How many Tools you can purchase total. Set 0 to disable", "Enable logging of the potential items Spawning in the shop.", "Players take no Damage in the Shop." }; public static string[] GetConfigDescriptions() { return DESCRIPTIONS; } } public class ConfigHelper { public static ConfigEntry<bool> CreateConfig(string section, string name, bool value, string description, int min, int max) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>())); } public static ConfigEntry<int> CreateConfig(string section, string name, int value, string description, int min, int max) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown return ((BaseUnityPlugin)Plugin.Instance).Config.Bind<int>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>())); } } public static class ItemConfigMapper { public static readonly Dictionary<itemType, (string shopKey, string purchaseKey, int offset)> Map = new Dictionary<itemType, (string, string, int)> { { (itemType)0, ("Max Drones In Shop", "Max Drone Purchase Amount", 0) }, { (itemType)1, ("Max Orbs In Shop", "Max Orb Purchase Amount", 0) }, { (itemType)3, ("Max Upgrades In Shop", "Max Upgrade Purchase Amount", 0) }, { (itemType)5, ("Max Crystals In Shop", "Max Crystal Purchase Amount", 1) }, { (itemType)6, ("Max Grenades In Shop", "Max Grenade Purchase Amount", 0) }, { (itemType)7, ("Max Melee Weapons In Shop", "Max Melee Weapon Purchase Amount", 0) }, { (itemType)8, ("Max Health-Packs In Shop", "Max Health-Pack Purchase Amount", 0) }, { (itemType)9, ("Max Guns In Shop", "Max Gun Purchase Amount", 0) }, { (itemType)10, ("Max Trackers In Shop", "Max Tracker Purchase Amount", 0) }, { (itemType)11, ("Max Mines In Shop", "Max Mine Purchase Amount", 0) }, { (itemType)2, ("Max Carts In Shop", "Max Cart Purchase Amount", 0) }, { (itemType)12, ("Max Pocket Carts In Shop", "Max Pocket Cart Purchase Amount", 0) }, { (itemType)13, ("Max Tools In Shop", "Max Tool Purchase Amount", 0) } }; } } namespace MoreShopItems.Compatability { internal static class MoreUpgradesMOD { public static bool isLoaded() { return Chainloader.PluginInfos.ContainsKey("bulletbot.moreupgrades"); } } internal static class NikkisUpgradesMOD { public static bool isLoaded() { return Chainloader.PluginInfos.ContainsKey("NikkiUpgrades"); } } internal static class VanillaUpgradesMOD { public static bool isLoaded() { return Chainloader.PluginInfos.ContainsKey("bulletbot.vanillaupgrades"); } } }