using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using MoreStandsForShops.Network; using MoreStandsForShops.Rewriters; using MoreStandsForShops.Shop; using MoreStandsForShops.Spawners; using MoreStandsForShops.Stands.Upgrade; using MoreStandsForShops.Utilities; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("MoreStandsForShops")] [assembly: AssemblyDescription("More shop stands for R.E.P.O.")] [assembly: AssemblyCompany("DarkSpider90")] [assembly: AssemblyProduct("MoreStandsForShops")] [assembly: AssemblyCopyright("Copyright (c) 2026 DarkSpider90")] [assembly: ComVisible(false)] [assembly: Guid("2BE30F9F-3160-41F9-BC85-989F4333B8B2")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("1.0.0.0")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MoreStandsForShops { public static class CleanPresetDatabase { private const string LevelPrefix = "Level Generator/Level/"; public static List GetSpawnPoints() { List list = new List(); list.Add(Point("center_extract_right_rear", "Module - Shop - N - Center Extract(Clone)", 7.04f, 0.03f, -5.075f, 270f, 34, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Center Extract(Clone)/WALLS/RIGHT/Not Connected/shop sign lynx" })); list.Add(Point("center_extract_right_mid", "Module - Shop - N - Center Extract(Clone)", 7.04f, 0.03f, -1.635f, 270f, 1, Array.Empty())); list.Add(Point("center_extract_top_mid", "Module - Shop - N - Center Extract(Clone)", 0.471f, 0.03f, 7.04f, 180f, 1, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Center Extract(Clone)/WALLS/TOP/Not Connected/Candy Shelf 2", "Main/Level Generator/Level/Module - Shop - N - Center Extract(Clone)/WALLS/TOP/Not Connected/Shop prop fridge" })); list.Add(Point("corner_stands_bottom_left", "Module - Shop - N - Corner Stands(Clone)", -1.72f, 0.03f, -7.04f, 0f, 1, new string[3] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/Shop Ice Cream Freezer", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/shop sign tyre (1)", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/shop sign tyre (2)" })); list.Add(Point("corner_stands_bottom_mid", "Module - Shop - N - Corner Stands(Clone)", 0.637f, 0.03f, -7.04f, 0f, 8, new string[3] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/Candy Shelf 2", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/Shop Ice Cream Freezer", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/BOT/Not Connected/shop sign tyre (1)" })); list.Add(Point("corner_stands_left_mid", "Module - Shop - N - Corner Stands(Clone)", -7.04f, 0.03f, -1.868f, 90f, 5, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/LEFT/Not Connected/Shop Ice Cream Freezer (1)" })); list.Add(Point("corner_stands_right_secret", "Module - Shop - N - Corner Stands(Clone)", 7.04f, 0.03f, -1.349f, 270f, 1, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder", "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/RIGHT/Not Connected/shop sign lynx" })); list.Add(Point("corner_stands_right_mid", "Module - Shop - N - Corner Stands(Clone)", 7.04f, 0.03f, -0.682f, 270f, 5, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder" })); list.Add(Point("corner_stands_top_mid", "Module - Shop - N - Corner Stands(Clone)", 0.054f, 0.03f, 7.04f, 180f, 9, Array.Empty())); list.Add(Point("middle_stands_left_secret", "Module - Shop - N - Middle Stands(Clone)", -7.04f, 0.03f, -1.385f, 90f, 1, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/LEFT/Not Connected/shop sign ai" })); list.Add(Point("middle_stands_left_mid", "Module - Shop - N - Middle Stands(Clone)", -7.04f, 0.03f, -0.481f, 90f, 1, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/LEFT/Not Connected/shop sign ai", "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/LEFT/Not Connected/shop sign hotdog" })); list.Add(Point("middle_stands_right_mid", "Module - Shop - N - Middle Stands(Clone)", 7.04f, 0.03f, -0.639f, 270f, 5, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder" })); list.Add(Point("middle_stands_top_left", "Module - Shop - N - Middle Stands(Clone)", -5.504f, 0.03f, 7.04f, 180f, 13, new string[2] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/RIGHT/Not Connected/Shop Magazine Holder", "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/TOP/Not Connected/Shop Magazine Stand (1)" })); list.Add(Point("middle_stands_top_car_service", "Module - Shop - N - Middle Stands(Clone)", -4.184f, 0.03f, 7.04f, 180f, 1, new string[1] { "Main/Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/WALLS/TOP/Connected/Soda Machine (1)" })); list.Add(Point("middle_stands_top_mid", "Module - Shop - N - Middle Stands(Clone)", 0.051f, 0.03f, 7.04f, 180f, 13, Array.Empty())); return list; } private static SpawnPointData Point(string id, string mainModule, float x, float y, float z, float yaw, int sourceCount, string[] disablePaths) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) return new SpawnPointData { VariantId = id, MainModule = "Level Generator/Level/" + mainModule, LocalPosition = new Vector3(x, y, z), LocalYaw = yaw, SourceCount = sourceCount, DisablePaths = disablePaths, RejectIfPresentPaths = Array.Empty() }; } } public class SpawnPointData { public string VariantId { get; set; } public string MainModule { get; set; } public Vector3 LocalPosition { get; set; } public float LocalYaw { get; set; } public int SourceCount { get; set; } public string[] DisablePaths { get; set; } = Array.Empty(); public string[] RejectIfPresentPaths { get; set; } = Array.Empty(); } public static class MyPluginInfo { public const string PLUGIN_GUID = "DarkSpider90.MoreStandsForShops"; public const string PLUGIN_NAME = "MoreStandsForShops"; public const string PLUGIN_VERSION = "1.1.0"; } [BepInPlugin("DarkSpider90.MoreStandsForShops", "MoreStandsForShops", "1.1.0")] public class Plugin : BaseUnityPlugin { internal static ConfigEntry EnableMod; internal static ConfigEntry EnableAdditionalUpgradeStand; internal static ConfigEntry EnableVanillaShelfTableRewrite; internal static ConfigEntry DisableShopPoolLimit; internal static ConfigEntry DebugLogs; internal static Dictionary> ItemCounts = new Dictionary>(); internal static Dictionary> SameItemCopies = new Dictionary>(); internal static Dictionary> ItemSpawnChances = new Dictionary>(); private static readonly string[] VanillaItemSpawnChanceNames = new string[70] { "Duct Taped Grenades", "Feather Drone", "Grenade", "Human Grenade", "Indestructible Drone", "Recharge Drone", "Roll Drone", "Rubber Duck", "Shockwave Grenade", "Stun Grenade", "Zero Gravity Drone", "Zero Gravity Orb", "Boltzap", "Explosive Mine", "Gun", "Pulse Pistol", "Shockwave Mine", "Shotgun", "Tranq Gun", "Trapzap", "Defibro", "Duck Bucket", "Frying Pan", "Phase Bridge", "Photon Blaster", "C.A.R.T.", "Energy Crystal", "Baseball Bat", "C.A.R.T. Cannon", "C.A.R.T. Laser", "Extraction Tracker", "Inflatable Hammer", "Leaf Blower", "Prodzap", "Roll Staff", "Semibot Walkies", "Sledge Hammer", "Sword", "Valuable Tracker", "Void Staff", "Zero Gravity Staff", "Autoscan Upgrade", "Crouch Rest Upgrade", "Death Head Battery Upgrade", "Extra Jump Upgrade", "Extra Life Upgrade", "Health Upgrade", "Item Resist Upgrade", "Item Value Upgrade", "Mana Regeneration Upgrade", "Map Enemy Tracker Upgrade", "Map Player Count Upgrade", "Map Player Tracker Upgrade", "Map Zoom Upgrade", "Range Upgrade", "Scout Cooldown Upgrade", "Sprint Speed Upgrade", "Sprint Usage Upgrade", "Stamina Upgrade", "Strength Upgrade", "Tumble Climb Upgrade", "Tumble Launch Upgrade", "Tumble Wings Upgrade", "Valuable Count Upgrade", "Large Health Pack (100)", "Medium Health Pack (50)", "Small Health Pack (25)", "POCKET C.A.R.T.", "Hauler", "Scout" }; private Harmony _harmony; internal static ManualLogSource Log { get; private set; } internal static Plugin Instance { get; private set; } private void Awake() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; LoadConfig(); _harmony = new Harmony("DarkSpider90.MoreStandsForShops"); _harmony.PatchAll(); Log.LogInfo((object)"MoreStandsForShops v1.1.0 loaded."); } private void LoadConfig() { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Expected O, but got Unknown //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Expected O, but got Unknown //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Expected O, but got Unknown //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Expected O, but got Unknown //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Expected O, but got Unknown //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Expected O, but got Unknown //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Expected O, but got Unknown //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Expected O, but got Unknown //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Expected O, but got Unknown //IL_04ec: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Expected O, but got Unknown //IL_0523: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Expected O, but got Unknown //IL_055a: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Expected O, but got Unknown //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_059b: Expected O, but got Unknown //IL_05c8: Unknown result type (might be due to invalid IL or missing references) //IL_05d2: Expected O, but got Unknown //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Expected O, but got Unknown EnableMod = ((BaseUnityPlugin)this).Config.Bind("General", "Enable Mod", true, "Enable or disable the entire mod."); EnableAdditionalUpgradeStand = ((BaseUnityPlugin)this).Config.Bind("General", "Enable Additional Upgrade Stand", true, "Spawn a second upgrade stand in the shop."); EnableVanillaShelfTableRewrite = ((BaseUnityPlugin)this).Config.Bind("General", "Enable Vanilla Shelf Table Rewrite", true, "Move small items to the lower health shelf and make vanilla table small slots accept medium/large/large_high items."); DisableShopPoolLimit = ((BaseUnityPlugin)this).Config.Bind("General", "Disable Shop Pool Limit", true, "Raise vanilla shop spawn budget to the filtered item pool size so free matching slots keep trying to fill."); DebugLogs = ((BaseUnityPlugin)this).Config.Bind("General", "Debug Logs", false, "Enable detailed debug logging for troubleshooting."); string text = "Item Counts"; ItemCounts["Upgrades Per Stand"] = ((BaseUnityPlugin)this).Config.Bind(text, "Upgrades Per Stand", 8, new ConfigDescription("Upgrade items per stand (0-14).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 14), Array.Empty())); ItemCounts["Total Upgrades"] = ((BaseUnityPlugin)this).Config.Bind(text, "Total Upgrades", 14, new ConfigDescription("Total upgrade items across the vanilla stand and passive second stand (0-28).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 28), Array.Empty())); ItemCounts["Drones"] = ((BaseUnityPlugin)this).Config.Bind(text, "Drones", 4, new ConfigDescription("Drone items to spawn (0-8).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 8), Array.Empty())); ItemCounts["Power Crystals"] = ((BaseUnityPlugin)this).Config.Bind(text, "Power Crystals", 3, new ConfigDescription("Power crystals (0-5).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 5), Array.Empty())); ItemCounts["Orbs"] = ((BaseUnityPlugin)this).Config.Bind(text, "Orbs", 1, new ConfigDescription("Orbs (0-3).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3), Array.Empty())); ItemCounts["Grenades"] = ((BaseUnityPlugin)this).Config.Bind(text, "Grenades", 4, new ConfigDescription("Grenades (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 6), Array.Empty())); ItemCounts["Mines"] = ((BaseUnityPlugin)this).Config.Bind(text, "Mines", 2, new ConfigDescription("Mines (0-3).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3), Array.Empty())); ItemCounts["Melee"] = ((BaseUnityPlugin)this).Config.Bind(text, "Melee", 4, new ConfigDescription("Melee weapons (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 6), Array.Empty())); ItemCounts["Guns"] = ((BaseUnityPlugin)this).Config.Bind(text, "Guns", 4, new ConfigDescription("Guns (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 6), Array.Empty())); ItemCounts["Launchers"] = ((BaseUnityPlugin)this).Config.Bind(text, "Launchers (Staff)", 2, new ConfigDescription("Launchers/staffs (0-6).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 6), Array.Empty())); ItemCounts["Tools"] = ((BaseUnityPlugin)this).Config.Bind(text, "Tools", 2, new ConfigDescription("Tools (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 4), Array.Empty())); ItemCounts["Health Packs"] = ((BaseUnityPlugin)this).Config.Bind(text, "Health Packs", 3, new ConfigDescription("Health packs (0-5).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 5), Array.Empty())); ItemCounts["Carts"] = ((BaseUnityPlugin)this).Config.Bind(text, "Carts", 2, new ConfigDescription("Carts (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 4), Array.Empty())); ItemCounts["Pocket Carts"] = ((BaseUnityPlugin)this).Config.Bind(text, "Pocket Carts", 1, new ConfigDescription("Pocket carts (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 4), Array.Empty())); ItemCounts["Vehicles"] = ((BaseUnityPlugin)this).Config.Bind(text, "Vehicles", 1, new ConfigDescription("Vehicles (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 4), Array.Empty())); ItemCounts["C.A.R.T. Weapons"] = ((BaseUnityPlugin)this).Config.Bind(text, "C.A.R.T. Weapons", 1, new ConfigDescription("Total C.A.R.T. Cannon and C.A.R.T. Laser items (0-4).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 4), Array.Empty())); string text2 = "Same Item Copies"; SameItemCopies["Upgrades"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Upgrades", 3, new ConfigDescription("Max copies of the same upgrade item (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Drones"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Drones", 2, new ConfigDescription("Max copies of the same drone (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Guns"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Guns", 2, new ConfigDescription("Max copies of the same gun (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Melee"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Melee", 2, new ConfigDescription("Max copies of the same melee weapon (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Launchers"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Launchers (Staff)", 2, new ConfigDescription("Max copies of the same launcher (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Grenades"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Grenades", 3, new ConfigDescription("Max copies of the same grenade (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Mines"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Mines", 2, new ConfigDescription("Max copies of the same mine (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["Health Packs"] = ((BaseUnityPlugin)this).Config.Bind(text2, "Health Packs", 2, new ConfigDescription("Max copies of the same health pack (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); SameItemCopies["C.A.R.T. Weapons"] = ((BaseUnityPlugin)this).Config.Bind(text2, "C.A.R.T. Weapons", 1, new ConfigDescription("Max copies of the same C.A.R.T. Cannon or C.A.R.T. Laser item (1-6).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 6), Array.Empty())); BindVanillaItemSpawnChanceConfigs(); } private static void BindVanillaItemSpawnChanceConfigs() { bool createdAny = false; string[] vanillaItemSpawnChanceNames = VanillaItemSpawnChanceNames; for (int i = 0; i < vanillaItemSpawnChanceNames.Length; i++) { BindItemSpawnChanceConfig(vanillaItemSpawnChanceNames[i], ref createdAny); } if (createdAny) { ((BaseUnityPlugin)Instance).Config.Save(); Log.LogInfo((object)$"Created vanilla item spawn chance config entries for {ItemSpawnChances.Count} items."); } } internal static void EnsureItemSpawnChanceConfigs(IEnumerable items) { if ((Object)(object)Instance == (Object)null || items == null) { return; } bool createdAny = false; foreach (Item item in items) { if (!((Object)(object)item == (Object)null)) { BindItemSpawnChanceConfig(ItemConfigName(item), ref createdAny); } } if (createdAny) { ((BaseUnityPlugin)Instance).Config.Save(); Log.LogInfo((object)$"Created/updated item spawn chance config entries for {ItemSpawnChances.Count} items."); } } internal static int GetItemSpawnChance(Item item) { if ((Object)(object)item == (Object)null) { return 0; } string key = ItemConfigName(item); if (!ItemSpawnChances.TryGetValue(key, out var value)) { return 100; } return value.Value; } private static void BindItemSpawnChanceConfig(string key, ref bool createdAny) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (!string.IsNullOrWhiteSpace(key) && !ItemSpawnChances.ContainsKey(key)) { ItemSpawnChances[key] = ((BaseUnityPlugin)Instance).Config.Bind("Item Spawn Chances", key, 100, new ConfigDescription("Relative spawn chance/weight for this exact item. 0 disables it in this mod's shop pools; 100 is default.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); createdAny = true; } } private static string ItemConfigName(Item item) { if ((Object)(object)item == (Object)null) { return ""; } if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } } } namespace MoreStandsForShops.Utilities { public static class ItemVolumeHelper { private static readonly Vector3[] CrystalSlotPositions = (Vector3[])(object)new Vector3[5] { new Vector3(-0.72f, 1.68f, 0.5f), new Vector3(-0.36f, 1.68f, 0.5f), new Vector3(0f, 1.68f, 0.5f), new Vector3(0.36f, 1.68f, 0.5f), new Vector3(0.72f, 1.68f, 0.5f) }; private static readonly Vector3[] DroneSlotPositions = (Vector3[])(object)new Vector3[8] { new Vector3(-0.77f, 1.18f, 0.5f), new Vector3(-0.55f, 1.18f, 0.5f), new Vector3(-0.33f, 1.18f, 0.5f), new Vector3(-0.11f, 1.18f, 0.5f), new Vector3(0.11f, 1.18f, 0.5f), new Vector3(0.33f, 1.18f, 0.5f), new Vector3(0.55f, 1.18f, 0.5f), new Vector3(0.77f, 1.18f, 0.5f) }; public static void AssignVolumesForDroneCrystalStand(GameObject stand) { //IL_0054: 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_00b9: Unknown result type (might be due to invalid IL or missing references) ItemVolume[] componentsInChildren = stand.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { CreateDroneCrystalVolumes(stand); return; } Array.Sort(componentsInChildren, (ItemVolume a, ItemVolume b) => ((Component)a).transform.position.y.CompareTo(((Component)b).transform.position.y)); int num = componentsInChildren.Length / 2; for (int i = 0; i < componentsInChildren.Length; i++) { bool flag = i < num; componentsInChildren[i].itemVolume = (itemVolume)((!flag) ? 4 : 0); componentsInChildren[i].itemSecretShopType = (itemSecretShopType)0; MoreStandsShelfVolume obj = ((Component)componentsInChildren[i]).gameObject.GetComponent() ?? ((Component)componentsInChildren[i]).gameObject.AddComponent(); obj.Zone = ((!flag) ? MoreStandsShelfZone.Crystal : MoreStandsShelfZone.Drone); obj.Handled = false; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)string.Format("[ItemVolumeHelper] Volume {0} (Y={1:F3}) -> {2}", ((Object)componentsInChildren[i]).name, ((Component)componentsInChildren[i]).transform.position.y, (i < num) ? "small" : "power_crystal")); } } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ItemVolumeHelper] Assigned {num} lower volume(s) to 'small' (drones) and {componentsInChildren.Length - num} upper volume(s) to 'power_crystal'."); } } private static void CreateDroneCrystalVolumes(GameObject stand) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)stand == (Object)null)) { for (int i = 0; i < CrystalSlotPositions.Length; i++) { CreateVolumeSlot(stand.transform, $"MoreStandsForShops Crystal Slot {i + 1:00}", (itemVolume)4, MoreStandsShelfZone.Crystal, CrystalSlotPositions[i]); } for (int j = 0; j < DroneSlotPositions.Length; j++) { CreateVolumeSlot(stand.transform, $"MoreStandsForShops Drone Slot {j + 1:00}", (itemVolume)0, MoreStandsShelfZone.Drone, DroneSlotPositions[j]); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ItemVolumeHelper] Created {CrystalSlotPositions.Length} crystal ItemVolume(s) and {DroneSlotPositions.Length} drone ItemVolume(s) on drone/crystal stand."); } } } private static ItemVolume CreateVolumeSlot(Transform parent, string name, itemVolume itemVolume, MoreStandsShelfZone zone, Vector3 localPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localRotation = Quaternion.identity; ItemVolume val2 = val.AddComponent(); val2.itemVolume = itemVolume; val2.itemSecretShopType = (itemSecretShopType)0; MoreStandsShelfVolume moreStandsShelfVolume = val.AddComponent(); moreStandsShelfVolume.Zone = zone; moreStandsShelfVolume.Handled = false; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ItemVolumeHelper] Created {name} zone={itemVolume} local={localPosition}."); } return val2; } } public sealed class MoreStandsMultiSizeVolume : MonoBehaviour { public string GroupId; } public enum MoreStandsShelfZone { Drone, Crystal, Grenade } public sealed class MoreStandsShelfVolume : MonoBehaviour { public MoreStandsShelfZone Zone; public bool Handled; } public sealed class MoreStandsUpgradeVolume : MonoBehaviour { } internal static class ScenePathUtility { public static Transform FindTransformByPath(string path) { if (string.IsNullOrWhiteSpace(path)) { return null; } return ShopSceneCache.Current.FindTransformByPath(path); } public static string GetTransformPath(Transform transform) { return ShopSceneCache.Current.GetTransformPath(transform); } public static List DisableExactPaths(IEnumerable paths, string logPrefix) { List list = new List(); HashSet hashSet = new HashSet(); if (paths == null) { return list; } foreach (string path in paths) { if (string.IsNullOrWhiteSpace(path) || !hashSet.Add(path)) { continue; } Transform val = FindTransformByPath(path); if ((Object)(object)val == (Object)null) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)(logPrefix + " Preset disable path not present: " + path)); } continue; } int num = DisableTree(val, list); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"{logPrefix} Disabled preset blocker: {GetTransformPath(val)} (nodes={num})"); } } return list; } private static int DisableTree(Transform root, List disabled) { if ((Object)(object)root == (Object)null) { return 0; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); int num = 0; Transform[] array = componentsInChildren; foreach (Transform val in array) { if (!((Object)(object)val == (Object)null) && (((Component)val).gameObject.activeSelf || ((Component)val).gameObject.activeInHierarchy)) { ((Component)val).gameObject.SetActive(false); disabled.Add(GetTransformPath(val)); num++; } } return num; } public static bool HasActivePath(IEnumerable paths, out string activePath) { activePath = null; if (paths == null) { return false; } foreach (string path in paths) { Transform val = FindTransformByPath(path); if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { activePath = GetTransformPath(val); return true; } } return false; } } internal sealed class ShopSceneCache { private static ShopSceneCache _current; private readonly Dictionary pathByInstanceId = new Dictionary(); private readonly Dictionary transformByPath = new Dictionary(StringComparer.Ordinal); private readonly int sceneHandle; internal GameObject[] Roots { get; } internal Transform[] Transforms { get; } internal ItemVolume[] ItemVolumes { get; } internal Renderer[] Renderers { get; } internal static ShopSceneCache Current { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); if (_current == null || _current.sceneHandle != ((Scene)(ref activeScene)).handle) { _current = new ShopSceneCache(); } return _current; } } private ShopSceneCache() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); sceneHandle = ((Scene)(ref activeScene)).handle; Roots = ((Scene)(ref activeScene)).GetRootGameObjects(); Transforms = (from transform in Resources.FindObjectsOfTypeAll() where (Object)(object)transform != (Object)null && ((Component)transform).gameObject.activeInHierarchy select transform).ToArray(); ItemVolumes = (from volume in Resources.FindObjectsOfTypeAll() where (Object)(object)volume != (Object)null && ((Component)volume).gameObject.activeInHierarchy select volume).ToArray(); Renderers = (from renderer in Resources.FindObjectsOfTypeAll() where (Object)(object)renderer != (Object)null && ((Component)renderer).gameObject.activeInHierarchy select renderer).ToArray(); Transform[] transforms = Transforms; foreach (Transform val in transforms) { string text = BuildPath(val); pathByInstanceId[((Object)val).GetInstanceID()] = text; if (!transformByPath.ContainsKey(text)) { transformByPath.Add(text, val); } } ConfigEntry debugLogs = Plugin.DebugLogs; if (debugLogs != null && debugLogs.Value) { Plugin.Log.LogInfo((object)($"[ShopSceneCache] Built scene cache: transforms={Transforms.Length}, " + $"itemVolumes={ItemVolumes.Length}, renderers={Renderers.Length}.")); } } internal static ShopSceneCache Rebuild() { _current = new ShopSceneCache(); return _current; } internal static void Clear() { _current = null; } internal Transform FindTransformByPath(string path) { if (string.IsNullOrWhiteSpace(path)) { return null; } string[] pathCandidates = GetPathCandidates(path); foreach (string text in pathCandidates) { if (transformByPath.TryGetValue(text, out var value) && (Object)(object)value != (Object)null && ((Component)value).gameObject.activeInHierarchy) { return value; } GameObject[] roots = Roots; foreach (GameObject val in roots) { if ((Object)(object)val == (Object)null) { continue; } Transform val2 = val.transform.Find(text); if ((Object)(object)val2 != (Object)null) { return val2; } if (text.StartsWith(((Object)val).name + "/", StringComparison.Ordinal)) { string text2 = text.Substring(((Object)val).name.Length + 1); val2 = val.transform.Find(text2); if ((Object)(object)val2 != (Object)null) { return val2; } } } } return null; } internal string GetTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return ""; } int instanceID = ((Object)transform).GetInstanceID(); if (pathByInstanceId.TryGetValue(instanceID, out var value)) { return value; } value = BuildPath(transform); pathByInstanceId[instanceID] = value; if (!transformByPath.ContainsKey(value)) { transformByPath.Add(value, transform); } return value; } private static string[] GetPathCandidates(string path) { string text = path.Trim().Trim('/'); if (!text.StartsWith("Main/", StringComparison.Ordinal)) { return new string[1] { text }; } return new string[2] { text, text.Substring("Main/".Length) }; } private static string BuildPath(Transform transform) { Stack stack = new Stack(); Transform val = transform; while ((Object)(object)val != (Object)null) { stack.Push(((Object)val).name); val = val.parent; } return string.Join("/", stack); } } } namespace MoreStandsForShops.Stands.Upgrade { internal sealed class UpgradeStandRerollController : MonoBehaviour, IOnEventCallback { private enum RerollState { Idle, Holding, Rollback, PressFail, PressSucceed, CloseHatch, RollStart, Rolling, RollEnd, OpenHatch, WaitingForHost, Broken } private readonly struct CachedUpgrade { internal readonly ItemUpgrade Upgrade; internal readonly Item Item; internal readonly Vector3 Position; internal readonly Quaternion Rotation; internal CachedUpgrade(ItemUpgrade upgrade, Item item, Vector3 position, Quaternion rotation) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Upgrade = upgrade; Item = item; Position = position; Rotation = rotation; } } private readonly struct PendingReplacement { internal readonly ItemUpgrade OriginalUpgrade; internal readonly Item Item; internal readonly Vector3 Position; internal readonly Quaternion Rotation; internal PendingReplacement(ItemUpgrade originalUpgrade, Item item, Vector3 position, Quaternion rotation) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) OriginalUpgrade = originalUpgrade; Item = item; Position = position; Rotation = rotation; } } private const byte RerollSyncEvent = 187; private const string SyncMagic = "MSFS_REROLL_V1"; private const string MsgHoldRequestStart = "HoldRequestStart"; private const string MsgHoldRequestStop = "HoldRequestStop"; private const string MsgHoldVisualStart = "HoldVisualStart"; private const string MsgHoldVisualStop = "HoldVisualStop"; private const string MsgHoldVisualProgress = "HoldVisualProgress"; private const string MsgRerollRequest = "RerollRequest"; private const string MsgRerollVisual = "RerollVisual"; private const string MsgBreakBuildUpVisual = "BreakBuildUpVisual"; private const string MsgBrokenVisual = "BrokenVisual"; private const float HoldProgressSyncInterval = 0.15f; private const float ButtonUseDistance = 3.25f; private const float ButtonCastRadius = 0.06f; private const float BuildUpStageDuration = 0.3f; private const float BuildUpFinalHoldDuration = 0.5f; [SerializeField] private Transform scanBox; [SerializeField] private Transform buttonRoot; [SerializeField] private Transform buttonColliderRoot; [SerializeField] private Transform hatch; [SerializeField] private Transform upgradeCompartment; [SerializeField] private Transform allMeshesTransform; [SerializeField] private StaticGrabObject buttonGrabObject; [SerializeField] private GameObject hatchClosed; [SerializeField] private GameObject hatchHurtCollider; [SerializeField] private GameObject rerollCompartmentHurtColliders; [SerializeField] private GameObject buttonRubble; [SerializeField] private GameObject fireHurtCollider; [SerializeField] private Light fireLight; [SerializeField] private Light buildUpLight; [SerializeField] private ParticleSystem hatchParticles; [SerializeField] private ParticleSystem rollingParticles; [SerializeField] private ParticleSystem particleButtonBreak; [SerializeField] private ParticleSystem particleFireLoop; [SerializeField] private ParticleSystem buildUpParticles; [SerializeField] private MeshRenderer buttonRenderer; [SerializeField] private Material buttonNormalMaterial; [SerializeField] private Material buttonDenyMaterial; [SerializeField] private LocalizedAsset interactLocalized; [SerializeField] private AnimationCurve buttonPressAnimationCurve; [SerializeField] private AnimationCurve buttonDenyCurve; [SerializeField] private AnimationCurve hatchAnimationCurve; [SerializeField] private AnimationCurve rollStartShakeCurve; [SerializeField] private AnimationCurve rollCurve; [SerializeField] private AnimationCurve rollEndShakeCurve; [SerializeField] private AnimationCurve buildUpIntroCurve; [SerializeField] private AnimationCurve buildUpOutroCurve; [SerializeField] private AnimationCurve flickerFadeLightCurve; [SerializeField] private BuildUpStage[] buildUpStages; [SerializeField] private SpringQuaternion meshRotationSpring; [SerializeField] private SpringVector3 meshPositionSpring; [SerializeField] private SpringFloat buttonRotationSpring; [SerializeField] private Sound soundButtonPress; [SerializeField] private Sound soundButtonDeny; [SerializeField] private Sound soundHatchClose; [SerializeField] private Sound soundRollStart; [SerializeField] private Sound soundRolling; [SerializeField] private Sound soundRollEnd; [SerializeField] private Sound soundHatchOpen; [SerializeField] private Sound soundButtonTwistUp; [SerializeField] private Sound soundButtonTwistDown; [SerializeField] private Sound soundStageBeep; [SerializeField] private Sound soundStateOn; [SerializeField] private Sound soundStateOff; [SerializeField] private Sound soundRerollStart; [SerializeField] private Sound soundRerollEnd; [SerializeField] private Sound soundRerollTick; [SerializeField] private Sound soundRerollSettle; [SerializeField] private Sound soundFinalRollSqueak; [SerializeField] private Sound soundHatchCloseImpact; [SerializeField] private Sound soundHatchOpenImpact; [SerializeField] private Sound soundButtonBreak; [SerializeField] private Sound soundBuildUpLoop; [SerializeField] private Sound soundFluorescentLightTurnOff; [SerializeField] private Sound soundLilButtonFire; private RerollState state; private Vector3 buttonOriginalPosition; private Vector3 hatchOriginalPosition; private Vector3 hatchOriginalScale; private Vector3 allMeshesOriginalPosition; private Quaternion buttonOriginalRotation; private Quaternion compartmentOriginalRotation; private Quaternion allMeshesOriginalRotation; private Color rollbackCurrentStageStartLightColor; private Color rollbackCurrentStageEndLightColor; private bool stateStart = true; private bool activationHeld; private bool activationStartedThisFrame; private bool activationReleasedThisFrame; private bool remoteHoldVisual; private bool holdVisualBroadcasted; private bool isBroken; private bool visualOnlyReroll; private bool finalRollSqueakPlayed; private bool hatchCloseImpactPlayed; private bool hatchOpenImpactPlayed; private bool fireActive; private bool[] chargeStageTriggered; private bool buildUpActive; private bool holdRequestSent; private bool resumeChargeFromRollback; private bool rollbackResumeRequested; private float stateTimer; private float stateTimerMax; private float chargeElapsed; private float buttonAnimationEval; private float buttonRotationTarget; private float buttonRotationAngle; private float buttonStageRotationAngle = 45f; private float hatchAnimationEval; private float compartmentAnimationEval; private float firePerlinOffsetX; private float firePerlinOffsetY; private float fireLightFadeInTimer; private float buildUpTimer; private float holdProgressSyncTimer; private float rollbackCurrentStageElapsed; private float rollbackCurrentStageStartEmission; private float rollbackCurrentStageStartLightIntensity; private float rollbackCurrentStageEndLightIntensity; private readonly List cachedUpgrades = new List(); private readonly List pendingReplacements = new List(); private int rollbackTopStage; private int rollbackCurrentStage = -1; private int rerollCount; private int maxRerollCount = -1; private int rerollTicksPlayed; private static readonly FieldInfo SpringQuaternionVelocityField = typeof(SpringQuaternion).GetField("springVelocity", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo SpringVector3VelocityField = typeof(SpringVector3).GetField("springVelocity", BindingFlags.Instance | BindingFlags.NonPublic); private int RerollCost => 5 + rerollCount * 5; private Vector3 ButtonSoundPosition { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)buttonRoot != (Object)null)) { return ((Component)this).transform.position; } return buttonRoot.position; } } private Vector3 HatchSoundPosition { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)hatch != (Object)null)) { return ((Component)this).transform.position; } return hatch.position; } } private Vector3 CompartmentSoundPosition { get { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)upgradeCompartment != (Object)null)) { return ((Component)this).transform.position; } return upgradeCompartment.position; } } private float HoldDuration { get { if (buildUpStages != null && buildUpStages.Length != 0) { return (float)buildUpStages.Length * 0.3f + 0.5f; } return 1.7f; } } private float ChargeStageDuration => 0.3f; public void OnEvent(EventData photonEvent) { if (photonEvent.Code != 187 || !(photonEvent.CustomData is object[] array) || array.Length < 2 || !(array[0] is string text) || text != "MSFS_REROLL_V1" || !(array[1] is string text2)) { return; } float syncedChargeElapsed = ((array.Length > 2) ? ReadProgressPayload(array[2], chargeElapsed) : chargeElapsed); if (isBroken && text2 != "BrokenVisual" && text2 != "BreakBuildUpVisual") { return; } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Sync] Event received. " + $"msg={text2}, sender={photonEvent.Sender}, " + $"isMaster={PhotonNetwork.IsMasterClient}, state={state}.")); } if (text2 == null) { return; } switch (text2.Length) { case 15: switch (text2[4]) { case 'R': if (text2 == "HoldRequestStop" && PhotonNetwork.IsMasterClient) { StopRemoteHoldVisual(syncedChargeElapsed); BroadcastHoldVisualStop(); } break; case 'V': if (text2 == "HoldVisualStart" && !PhotonNetwork.IsMasterClient) { BeginRemoteHoldVisual(syncedChargeElapsed); } break; } break; case 18: switch (text2[0]) { case 'H': if (text2 == "HoldVisualProgress" && !PhotonNetwork.IsMasterClient) { ApplyRemoteHoldProgress(syncedChargeElapsed); } break; case 'B': if (text2 == "BreakBuildUpVisual" && !PhotonNetwork.IsMasterClient) { StartBreakBuildUpVisual(); } break; } break; case 12: switch (text2[0]) { case 'R': if (text2 == "RerollVisual" && !PhotonNetwork.IsMasterClient) { BeginVisualReroll(); } break; case 'B': if (text2 == "BrokenVisual" && !PhotonNetwork.IsMasterClient) { BreakButton(); } break; } break; case 16: if (text2 == "HoldRequestStart" && PhotonNetwork.IsMasterClient) { BeginRemoteHoldVisual(syncedChargeElapsed); BroadcastHoldVisualStart(); } break; case 14: if (text2 == "HoldVisualStop" && !PhotonNetwork.IsMasterClient) { StopRemoteHoldVisual(syncedChargeElapsed); } break; case 13: if (text2 == "RerollRequest" && PhotonNetwork.IsMasterClient) { TryStartReroll(visualOnly: false, broadcastVisual: true); } break; case 17: break; } } private void RaiseRerollEvent(string message, ReceiverGroup receivers, float? progress = null) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0063: Expected O, but got Unknown if (SemiFunc.IsMultiplayer()) { object[] array = ((!progress.HasValue) ? new object[2] { "MSFS_REROLL_V1", message } : new object[3] { "MSFS_REROLL_V1", message, progress.Value }); PhotonNetwork.RaiseEvent((byte)187, (object)array, new RaiseEventOptions { Receivers = receivers }, SendOptions.SendReliable); } } private void BroadcastRerollVisual() { RaiseRerollEvent("RerollVisual", (ReceiverGroup)0); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Broadcast reroll visual."); } } private void BroadcastHoldVisualStop() { if (!holdVisualBroadcasted) { return; } holdVisualBroadcasted = false; holdProgressSyncTimer = 0f; if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { float num = Mathf.Clamp(chargeElapsed, 0f, HoldDuration); RaiseRerollEvent("HoldVisualStop", (ReceiverGroup)0, num); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.Sync] Broadcast hold visual stop. progress={num:0.00}."); } } } private void BroadcastHoldVisualProgress(bool force) { if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient && holdVisualBroadcasted) { holdProgressSyncTimer += Time.deltaTime; if (force || !(holdProgressSyncTimer < 0.15f)) { holdProgressSyncTimer = 0f; RaiseRerollEvent("HoldVisualProgress", (ReceiverGroup)0, Mathf.Clamp(chargeElapsed, 0f, HoldDuration)); } } } private void BroadcastHoldVisualStart() { if (holdVisualBroadcasted) { return; } holdVisualBroadcasted = true; holdProgressSyncTimer = 0f; if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { float num = Mathf.Clamp(chargeElapsed, 0f, HoldDuration); RaiseRerollEvent("HoldVisualStart", (ReceiverGroup)0, num); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.Sync] Broadcast hold visual start. progress={num:0.00}."); } } } private void BeginVisualReroll() { if (state != 0 && state != RerollState.WaitingForHost && state != RerollState.Holding && state != RerollState.Rollback) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.Sync] Ignored visual reroll in state={state}."); } } else { remoteHoldVisual = false; holdRequestSent = false; visualOnlyReroll = true; StateSet(RerollState.PressSucceed); } } private void BeginRemoteHoldVisual(float syncedChargeElapsed = -1f) { if (isBroken) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Ignored remote hold visual: stand is broken."); } return; } if (state != 0 && state != RerollState.Rollback && state != RerollState.WaitingForHost) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.Sync] Ignored remote hold visual in state={state}."); } return; } if (syncedChargeElapsed >= 0f) { chargeElapsed = Mathf.Clamp(syncedChargeElapsed, 0f, HoldDuration); resumeChargeFromRollback = chargeElapsed > 0f; } else { resumeChargeFromRollback = state == RerollState.Rollback; } remoteHoldVisual = true; visualOnlyReroll = true; StateSet(RerollState.Holding); } private void StopRemoteHoldVisual(float syncedChargeElapsed = -1f) { if (remoteHoldVisual) { remoteHoldVisual = false; if (syncedChargeElapsed >= 0f) { chargeElapsed = Mathf.Clamp(syncedChargeElapsed, 0f, HoldDuration); } if (state == RerollState.Holding) { StateSet(RerollState.Rollback); } } } private void ApplyRemoteHoldProgress(float syncedChargeElapsed) { if (remoteHoldVisual && state == RerollState.Holding) { chargeElapsed = Mathf.Clamp(syncedChargeElapsed, 0f, HoldDuration); SyncChargeStageTriggers(chargeElapsed); ApplyChargeVisualsSilent(chargeElapsed); } } private void RequestHostReroll() { if (SemiFunc.IsMultiplayer()) { RaiseRerollEvent("RerollRequest", (ReceiverGroup)2); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Sent reroll request to host."); } } } private void RequestHostHoldStart() { if (!holdRequestSent && SemiFunc.IsMultiplayer() && !PhotonNetwork.IsMasterClient) { holdRequestSent = true; RaiseRerollEvent("HoldRequestStart", (ReceiverGroup)2, Mathf.Clamp(chargeElapsed, 0f, HoldDuration)); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Sent hold-start request to host."); } } } private void RequestHostHoldStop() { if (holdRequestSent && SemiFunc.IsMultiplayer() && !PhotonNetwork.IsMasterClient) { holdRequestSent = false; RaiseRerollEvent("HoldRequestStop", (ReceiverGroup)2, Mathf.Clamp(chargeElapsed, 0f, HoldDuration)); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Sent hold-stop request to host."); } } } private void BroadcastBroken() { if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { RaiseRerollEvent("BrokenVisual", (ReceiverGroup)0); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Broadcast broken visual."); } } } private void BroadcastBreakBuildUpVisual() { if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { RaiseRerollEvent("BreakBuildUpVisual", (ReceiverGroup)0); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Sync] Broadcast break build-up visual."); } } } private static float ReadProgressPayload(object data, float fallback) { if (!(data is float result)) { if (!(data is double num)) { if (data is int num2) { return num2; } return fallback; } return (float)num; } return result; } private void OnEnable() { PhotonNetwork.AddCallbackTarget((object)this); } private void OnDisable() { PhotonNetwork.RemoveCallbackTarget((object)this); } private void Start() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown ResolveReferences(); CaptureOriginalTransforms(); DisableVanillaButtonNetworking(); ResetBuildUpVisuals(); if (buildUpStages == null || buildUpStages.Length == 0) { buildUpStages = (BuildUpStage[])(object)new BuildUpStage[4]; } chargeStageTriggered = new bool[buildUpStages.Length]; buttonStageRotationAngle = 180f / (float)Mathf.Max(1, buildUpStages.Length); if (buttonRotationSpring == null) { buttonRotationSpring = new SpringFloat(); } if (meshRotationSpring == null) { meshRotationSpring = new SpringQuaternion(); } if (meshPositionSpring == null) { meshPositionSpring = new SpringVector3(); } buttonRotationSpring.speed = 80f; buttonRotationSpring.damping = 0.25f; SpringQuaternion obj = meshRotationSpring; obj.speed *= 0.75f; SpringVector3 obj2 = meshPositionSpring; obj2.speed *= 0.75f; if ((Object)(object)buttonRenderer != (Object)null && (Object)(object)buttonNormalMaterial != (Object)null) { ((Renderer)buttonRenderer).material = buttonNormalMaterial; } if ((Object)(object)buttonRubble != (Object)null) { buttonRubble.SetActive(false); } if ((Object)(object)fireHurtCollider != (Object)null) { fireHurtCollider.SetActive(false); } if ((Object)(object)fireLight != (Object)null) { ((Component)fireLight).gameObject.SetActive(false); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll] Controller ready. scanBox=" + NameOrNull(scanBox) + ", button=" + NameOrNull(buttonRoot) + ", collider=" + NameOrNull(buttonColliderRoot) + ".")); } } private void Update() { ReadActivationInput(); bool buttonFocused = IsLocalPlayerLookingAtButton(); UpdateHover(buttonFocused); UpdateState(buttonFocused); UpdateButtonRotationSpring(); ApplyButtonRotation(); UpdateMeshSprings(); UpdateFire(); UpdateBuildUpLoop(); if (stateTimer <= stateTimerMax) { stateTimer += Time.deltaTime; } } private void ReadActivationInput() { activationStartedThisFrame = false; activationReleasedThisFrame = false; if (!((Object)(object)InputManager.instance == (Object)null)) { if (InputManager.instance.KeyDown((InputKey)10) || InputManager.instance.KeyDown((InputKey)2)) { activationHeld = true; activationStartedThisFrame = true; } if (InputManager.instance.KeyUp((InputKey)10) || InputManager.instance.KeyUp((InputKey)2)) { activationHeld = false; activationReleasedThisFrame = true; } } } private void UpdateHover(bool buttonFocused) { bool flag = !buttonFocused || isBroken; if (!flag) { RerollState rerollState = state; bool flag2 = (uint)rerollState <= 2u; flag = !flag2; } if (!flag) { if ((Object)(object)Aim.instance != (Object)null) { Aim.instance.SetState((State)((state != RerollState.Holding) ? 1 : 2)); } string text = BuildHoverText(); if ((Object)(object)buttonGrabObject != (Object)null) { buttonGrabObject.hoverText = text; buttonGrabObject.ShowHoverText(); } else if ((Object)(object)ItemInfoUI.instance != (Object)null) { ItemInfoUI.instance.ItemInfoText((ItemAttributes)null, text, false); } } } private string BuildHoverText() { string text = "-" + SemiFunc.DollarGetString(RerollCost) + "k"; if ((Object)(object)interactLocalized != (Object)null) { return interactLocalized.GetLocalizedString((IList)new object[1] { new { cost = text } }); } return "Reroll upgrades " + text; } private bool IsLocalPlayerLookingAtButton() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null || (Object)(object)val.localCamera == (Object)null) { return false; } Transform overrideTransform = val.localCamera.GetOverrideTransform(); if ((Object)(object)overrideTransform == (Object)null) { return false; } Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(overrideTransform.position, overrideTransform.forward); RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val2, ref val3, 3.25f, -1, (QueryTriggerInteraction)2) && IsButtonTarget(((RaycastHit)(ref val3)).transform)) { return true; } foreach (RaycastHit item in from h in Physics.SphereCastAll(val2, 0.06f, 3.25f, -1, (QueryTriggerInteraction)2) orderby ((RaycastHit)(ref h)).distance select h) { RaycastHit current = item; if (!((Object)(object)((RaycastHit)(ref current)).transform == (Object)null) && IsButtonTarget(((RaycastHit)(ref current)).transform)) { return true; } } return false; } private bool IsButtonTarget(Transform hitTransform) { if ((Object)(object)hitTransform == (Object)null) { return false; } if ((Object)(object)buttonRoot != (Object)null && ((Object)(object)hitTransform == (Object)(object)buttonRoot || hitTransform.IsChildOf(buttonRoot))) { return true; } if ((Object)(object)buttonColliderRoot != (Object)null && ((Object)(object)hitTransform == (Object)(object)buttonColliderRoot || hitTransform.IsChildOf(buttonColliderRoot))) { return true; } StaticGrabObject componentInParent = ((Component)hitTransform).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return (Object)(object)componentInParent == (Object)(object)buttonGrabObject; } return false; } private List BuildPendingReplacements(List upgrades) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) Dictionary displayedCounts = BuildDisplayedCounts(upgrades); Dictionary dictionary = new Dictionary(); List list = new List(); foreach (CachedUpgrade upgrade in upgrades) { Item val = SelectReplacement(upgrade.Item, displayedCounts, dictionary); if (!((Object)(object)val == (Object)null)) { string key = ItemKey(val); dictionary[key] = ((!dictionary.TryGetValue(key, out var value)) ? 1 : (value + 1)); list.Add(new PendingReplacement(upgrade.Upgrade, val, upgrade.Position, upgrade.Rotation)); } } if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] Built replacement list. " + $"source={upgrades.Count}, replacements={list.Count}.")); } return list; } private List ScanUpgradesInside() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if ((Object)(object)scanBox == (Object)null) { Plugin.Log.LogWarning((object)"[UpgradeStandReroll.Items] Missing scan box; cannot scan upgrades."); return list; } HashSet hashSet = new HashSet(); Collider[] array = Physics.OverlapBox(scanBox.position, scanBox.localScale * 0.5f, scanBox.rotation); Collider[] array2 = array; foreach (Collider val in array2) { ItemUpgrade val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent(); if (!((Object)(object)val2 == (Object)null) && hashSet.Add(val2)) { ItemAttributes component = ((Component)val2).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.item == (Object)null)) { list.Add(new CachedUpgrade(val2, component.item, ((Component)val2).transform.position, ((Component)val2).transform.rotation)); } } } if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] Scan complete. " + $"colliders={array.Length}, upgrades={list.Count}, " + $"scanBox={NameOrNull(scanBox)}, position={scanBox.position}, scale={scanBox.localScale}.")); } return list; } private void DestroyCachedUpgrades() { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.Items] Destroying cached upgrades. count={pendingReplacements.Count}."); } foreach (PendingReplacement pendingReplacement in pendingReplacements) { DestroyUpgrade(pendingReplacement.OriginalUpgrade); } } private void SpawnPendingReplacements() { //IL_004e: 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) if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.Items] Spawning replacement upgrades. count={pendingReplacements.Count}."); } foreach (PendingReplacement pendingReplacement in pendingReplacements) { SpawnReplacement(pendingReplacement.Item, pendingReplacement.Position, pendingReplacement.Rotation); } } private static Dictionary BuildDisplayedCounts(IEnumerable upgrades) { Dictionary dictionary = new Dictionary(); foreach (CachedUpgrade upgrade in upgrades) { string key = ItemKey(upgrade.Item); dictionary[key] = ((!dictionary.TryGetValue(key, out var value)) ? 1 : (value + 1)); } return dictionary; } private static Item SelectReplacement(Item previous, Dictionary displayedCounts, Dictionary selectedCounts) { return SelectReplacementInternal(previous, displayedCounts, selectedCounts, allowPrevious: false) ?? SelectReplacementInternal(previous, displayedCounts, selectedCounts, allowPrevious: true); } private static Item SelectReplacementInternal(Item previous, Dictionary displayedCounts, Dictionary selectedCounts, bool allowPrevious) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Invalid comparison between Unknown and I4 if ((Object)(object)StatsManager.instance == (Object)null) { return null; } ConfigEntry value; int num = (Plugin.SameItemCopies.TryGetValue("Upgrades", out value) ? value.Value : 6); int num2 = ((!((Object)(object)GameDirector.instance != (Object)null)) ? 1 : GameDirector.instance.PlayerList.Count); List<(Item, int)> list = new List<(Item, int)>(); foreach (Item value4 in StatsManager.instance.itemDictionary.Values) { if ((Object)(object)value4 == (Object)null || value4.disabled || (int)value4.itemType != 3 || (!allowPrevious && (Object)(object)value4 == (Object)(object)previous)) { continue; } int itemSpawnChance = Plugin.GetItemSpawnChance(value4); if (itemSpawnChance > 0) { string key = ItemKey(value4); int value2; int num3 = (displayedCounts.TryGetValue(key, out value2) ? value2 : 0); int value3; int num4 = (selectedCounts.TryGetValue(key, out value3) ? value3 : 0); int num5 = SemiFunc.StatGetItemsPurchased(((Object)value4).name); if (num3 + num4 < num && (value4.maxAmountInShop <= 0 || num5 + num3 + num4 < value4.maxAmountInShop) && (!value4.maxPurchase || StatsManager.instance.GetItemsUpgradesPurchasedTotal(((Object)value4).name) < value4.maxPurchaseAmount) && (value4.minPlayerCount <= 1 || num2 >= value4.minPlayerCount)) { list.Add((value4, Mathf.Max(1, itemSpawnChance))); } } } if (list.Count == 0) { if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] No replacement candidates. " + $"previous={ItemKey(previous)}, allowPrevious={allowPrevious}, sameLimit={num}.")); } return null; } int num6 = list.Sum<(Item, int)>(((Item item, int weight) candidate) => candidate.weight); int num7 = Random.Range(0, num6); foreach (var (val, num8) in list) { if (num7 < num8) { if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] Selected replacement. previous=" + ItemKey(previous) + ", selected=" + ((Object)val).name + ", " + $"allowPrevious={allowPrevious}, candidates={list.Count}, totalWeight={num6}.")); } return val; } num7 -= num8; } Item item = list[list.Count - 1].Item1; if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] Selected fallback replacement. " + $"previous={ItemKey(previous)}, selected={((Object)item).name}, candidates={list.Count}.")); } return item; } private static void DestroyUpgrade(ItemUpgrade upgrade) { if (!((Object)(object)upgrade == (Object)null)) { PhotonView component = ((Component)upgrade).GetComponent(); GameObject val = (((Object)(object)component != (Object)null) ? ((Component)component).gameObject : ((Component)upgrade).gameObject); if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] Destroy upgrade. " + $"object={((Object)val).name}, hasPhotonView={(Object)(object)component != (Object)null}, multiplayer={SemiFunc.IsMultiplayer()}.")); } if (SemiFunc.IsMultiplayer() && (Object)(object)component != (Object)null) { PhotonNetwork.Destroy(val); } else { Object.Destroy((Object)(object)val); } } } private void SpawnReplacement(Item item, Vector3 position, Quaternion fallbackRotation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_00a8: Unknown result type (might be due to invalid IL or missing references) Quaternion val = fallbackRotation; if ((Object)(object)ShopManager.instance != (Object)null && (Object)(object)ShopManager.instance.itemRotateHelper != (Object)null) { Transform transform = ((Component)ShopManager.instance.itemRotateHelper).transform; transform.parent = ((Component)this).transform; transform.position = position; transform.localRotation = item.spawnRotationOffset; val = transform.rotation; transform.parent = ((Component)ShopManager.instance).transform; } if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Items] Spawn replacement. " + $"item={((Object)item).name}, position={position}, rotation={((Quaternion)(ref val)).eulerAngles}, multiplayer={SemiFunc.IsMultiplayer()}.")); } if (SemiFunc.IsMultiplayer()) { PhotonNetwork.InstantiateRoomObject(item.prefab.ResourcePath, position, val, (byte)0, (object[])null); } else { Object.Instantiate(item.prefab.Prefab, position, val); } } private static string ItemKey(Item item) { if (!((Object)(object)item == (Object)null)) { return ((Object)item).name; } return string.Empty; } private void ResolveReferences() { if ((Object)(object)buttonRoot == (Object)null) { buttonRoot = FindChildByNamePart(((Component)this).transform, "button"); } if ((Object)(object)buttonGrabObject == (Object)null) { buttonGrabObject = ((Component)this).GetComponentsInChildren(true).FirstOrDefault(); } if ((Object)(object)buttonColliderRoot == (Object)null && (Object)(object)buttonGrabObject != (Object)null) { buttonColliderRoot = buttonGrabObject.colliderTransform; } if ((Object)(object)scanBox == (Object)null) { scanBox = FindChildByNameParts(((Component)this).transform, "upgrade", "inside", "box"); } if ((Object)(object)scanBox == (Object)null) { scanBox = FindChildByNameParts(((Component)this).transform, "inside", "box"); } if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.References] Resolved. button=" + NameOrNull(buttonRoot) + ", buttonCollider=" + NameOrNull(buttonColliderRoot) + ", scanBox=" + NameOrNull(scanBox) + ", hatch=" + NameOrNull(hatch) + ", compartment=" + NameOrNull(upgradeCompartment) + ", allMeshes=" + NameOrNull(allMeshesTransform) + ".")); } } private void CaptureOriginalTransforms() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)buttonRoot != (Object)null) { buttonOriginalPosition = buttonRoot.localPosition; buttonOriginalRotation = buttonRoot.localRotation; } if ((Object)(object)hatch != (Object)null) { hatchOriginalPosition = hatch.localPosition; hatchOriginalScale = hatch.localScale; } if ((Object)(object)upgradeCompartment != (Object)null) { compartmentOriginalRotation = upgradeCompartment.localRotation; } if ((Object)(object)allMeshesTransform != (Object)null) { allMeshesOriginalPosition = allMeshesTransform.localPosition; allMeshesOriginalRotation = allMeshesTransform.localRotation; } } private void DisableVanillaButtonNetworking() { int num = 0; int num2 = 0; int num3 = 0; PhysGrabObjectGrabArea[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; num++; } StaticGrabObject[] componentsInChildren2 = ((Component)this).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { ((Behaviour)componentsInChildren2[i]).enabled = false; num2++; } PhotonView[] componentsInChildren3 = ((Component)this).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { ((Behaviour)componentsInChildren3[i]).enabled = false; num3++; } if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.References] Disabled vanilla button networking. " + $"grabAreas={num}, staticGrabs={num2}, photonViews={num3}.")); } } private static Transform FindChildByNamePart(Transform root, string part) { string value = part.ToLowerInvariant(); Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name.ToLowerInvariant().Contains(value)) { return val; } } return null; } private static Transform FindChildByNameParts(Transform root, params string[] parts) { Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { string text = ((Object)val).name.ToLowerInvariant(); bool flag = true; foreach (string text2 in parts) { if (!text.Contains(text2.ToLowerInvariant())) { flag = false; break; } } if (flag) { return val; } } return null; } private static string NameOrNull(Transform transform) { if (!((Object)(object)transform == (Object)null)) { return ((Object)transform).name; } return ""; } private void TryStartReroll(bool visualOnly, bool broadcastVisual) { if (state != RerollState.Holding && state != 0) { return; } if (visualOnly) { visualOnlyReroll = true; StateSet(RerollState.PressSucceed); } else { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } if (isBroken) { StateSet(RerollState.PressFail); return; } List list = ScanUpgradesInside(); if (list.Count == 0) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll] Reroll skipped: no upgrades inside stand."); } StateSet(RerollState.PressFail); return; } int rerollCost = RerollCost; if (SemiFunc.StatGetRunCurrency() < rerollCost) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll] Reroll skipped: not enough currency. cost={rerollCost}, current={SemiFunc.StatGetRunCurrency()}."); } StateSet(RerollState.PressFail); return; } List list2 = BuildPendingReplacements(list); if (list2.Count == 0) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll] Reroll skipped: no valid replacement upgrades."); } StateSet(RerollState.PressFail); return; } SemiFunc.StatSetRunCurrency(SemiFunc.StatGetRunCurrency() - rerollCost); if ((Object)(object)CurrencyUI.instance != (Object)null) { CurrencyUI.instance.FetchCurrency(); } if (maxRerollCount < 0) { maxRerollCount = Random.Range(1, 4); } rerollCount++; cachedUpgrades.Clear(); cachedUpgrades.AddRange(list); pendingReplacements.Clear(); pendingReplacements.AddRange(list2); visualOnlyReroll = false; BroadcastHoldVisualStop(); if (broadcastVisual) { BroadcastRerollVisual(); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll] Reroll accepted. upgrades={list.Count}, replacements={list2.Count}, cost={rerollCost}, rerollCount={rerollCount}, maxBeforeBreak={maxRerollCount}."); } StateSet(RerollState.PressSucceed); } } private bool CanAttemptRerollLocally() { if (isBroken) { return false; } if (SemiFunc.StatGetRunCurrency() < RerollCost) { return false; } return (Object)(object)scanBox != (Object)null; } private void UpdateState(bool buttonFocused) { switch (state) { case RerollState.Idle: StateIdle(buttonFocused); break; case RerollState.Holding: StateHolding(buttonFocused); break; case RerollState.Rollback: StateRollback(buttonFocused); break; case RerollState.PressFail: StatePressFail(); break; case RerollState.PressSucceed: StatePressSucceed(); break; case RerollState.CloseHatch: StateCloseHatch(); break; case RerollState.RollStart: StateRollStart(); break; case RerollState.Rolling: StateRolling(); break; case RerollState.RollEnd: StateRollEnd(); break; case RerollState.OpenHatch: StateOpenHatch(); break; case RerollState.WaitingForHost: StateWaitingForHost(); break; case RerollState.Broken: StateBroken(); break; } } private void StateIdle(bool buttonFocused) { if (stateStart) { stateTimerMax = 0f; stateTimer = 0f; visualOnlyReroll = false; buttonAnimationEval = 0f; chargeElapsed = 0f; buttonRotationTarget = 0f; SetButtonPositionPressed(0f); SetButtonNormal(); ResetBuildUpVisuals(); stateStart = false; remoteHoldVisual = false; holdRequestSent = false; holdVisualBroadcasted = false; resumeChargeFromRollback = false; holdProgressSyncTimer = 0f; rollbackTopStage = 0; rollbackCurrentStage = -1; rollbackCurrentStageElapsed = 0f; rollbackCurrentStageStartEmission = 0f; rollbackResumeRequested = false; } if (isBroken) { StateSet(RerollState.Broken); } else if (buttonFocused && activationStartedThisFrame) { if (!CanAttemptRerollLocally()) { StateSet(RerollState.PressFail); } else { StateSet(RerollState.Holding); } } } private void StateHolding(bool buttonFocused) { if (stateStart) { stateTimerMax = HoldDuration; stateTimer = 0f; if (resumeChargeFromRollback) { chargeElapsed = Mathf.Clamp(chargeElapsed, 0f, HoldDuration); SyncChargeStageTriggers(chargeElapsed); ApplyChargeVisualsSilent(chargeElapsed); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.State] Resume charging from rollback. chargeElapsed={chargeElapsed:0.00}."); } } else { chargeElapsed = 0f; buttonRotationTarget = 0f; ResetChargeStageTriggers(); ResetBuildUpVisuals(); } resumeChargeFromRollback = false; if ((Object)(object)buildUpLight != (Object)null) { ((Component)buildUpLight).gameObject.SetActive(true); } stateStart = false; if (!remoteHoldVisual) { if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { BroadcastHoldVisualStart(); } else if (SemiFunc.IsMultiplayer()) { RequestHostHoldStart(); } } } if (!remoteHoldVisual && (!activationHeld || activationReleasedThisFrame || !buttonFocused)) { if (PhotonNetwork.IsMasterClient) { BroadcastHoldVisualStop(); } else { RequestHostHoldStop(); } StateSet(RerollState.Rollback); return; } chargeElapsed += Time.deltaTime; UpdateChargeVisuals(chargeElapsed); if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { BroadcastHoldVisualProgress(force: false); } if (chargeElapsed >= HoldDuration) { if (remoteHoldVisual) { chargeElapsed = HoldDuration; UpdateChargeVisuals(chargeElapsed); } else if (SemiFunc.IsMasterClientOrSingleplayer()) { TryStartReroll(visualOnly: false, broadcastVisual: true); } else if (SemiFunc.IsMultiplayer()) { holdRequestSent = false; RequestHostReroll(); StateSet(RerollState.WaitingForHost); } else { StateSet(RerollState.PressFail); } } } private void StateRollback(bool buttonFocused) { BroadcastHoldVisualStop(); if (stateStart) { rollbackResumeRequested = false; rollbackTopStage = Mathf.Clamp(Mathf.FloorToInt(chargeElapsed / ChargeStageDuration), 0, Mathf.Max(0, buildUpStages.Length - 1)); BeginRollbackStage(rollbackTopStage); if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.State] Stage rollback started. " + $"chargeElapsed={chargeElapsed:0.00}, topStage={rollbackTopStage}.")); } stateTimer = 0f; stateTimerMax = 0f; stateStart = false; } if (rollbackCurrentStage < 0) { return; } if (!remoteHoldVisual && buttonFocused && activationStartedThisFrame) { rollbackResumeRequested = true; } rollbackCurrentStageElapsed += Time.deltaTime; float num = Mathf.Clamp01(rollbackCurrentStageElapsed / 0.5f); float eased = (SemiFunc.Photosensitivity() ? num : Evaluate(buildUpOutroCurve, num)); ApplyRollbackStageVisuals(eased); if (num < 1f) { return; } ApplyStageEmission(buildUpStages[rollbackCurrentStage], 0f); if (!remoteHoldVisual && rollbackResumeRequested) { ResumeChargingFromRollback(rollbackCurrentStage); return; } rollbackCurrentStage--; if (rollbackCurrentStage < 0) { chargeElapsed = 0f; ResetBuildUpVisuals(); buttonRotationTarget = 0f; StateSet(RerollState.Idle); } else { BeginRollbackStage(rollbackCurrentStage); } } private void StatePressFail() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 0.3f; stateTimer = 0f; buttonAnimationEval = 0f; buttonRotationTarget = 0f; SetButtonDeny(); if (soundButtonDeny != null) { soundButtonDeny.Play(ButtonSoundPosition, 1f, 1f, 1f, 1f); } ShakeButton(); stateStart = false; } buttonAnimationEval = Mathf.Clamp01(buttonAnimationEval + 3f * Time.deltaTime); buttonRotationTarget = 22.5f * Evaluate(buttonDenyCurve, buttonAnimationEval); if (stateTimer >= stateTimerMax) { StateSet(isBroken ? RerollState.Broken : RerollState.Idle); } } private void StatePressSucceed() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 0.3f; stateTimer = 0f; buttonAnimationEval = 0f; if (soundButtonPress != null) { soundButtonPress.Play(ButtonSoundPosition, 1f, 1f, 1f, 1f); } ShakeButton(); stateStart = false; } buttonAnimationEval = Mathf.Clamp01(buttonAnimationEval + 8f * Time.deltaTime); SetButtonPositionPressed(Evaluate(buttonPressAnimationCurve, buttonAnimationEval)); if (stateTimer >= stateTimerMax) { StateSet(RerollState.CloseHatch); } } private void StateCloseHatch() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 0.4f; stateTimer = 0f; hatchAnimationEval = 0f; hatchCloseImpactPlayed = false; if ((Object)(object)hatchParticles != (Object)null) { hatchParticles.Play(true); } if (soundHatchClose != null) { soundHatchClose.Play(HatchSoundPosition, 1f, 1f, 1f, 1f); } if (soundRerollStart != null) { soundRerollStart.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f); } ShakeHatch(); stateStart = false; } hatchAnimationEval = Mathf.Clamp01(stateTimer / stateTimerMax); ApplyHatchClosed(hatchAnimationEval); if (hatchAnimationEval >= 0.2f) { if ((Object)(object)hatchClosed != (Object)null) { hatchClosed.SetActive(true); } if ((Object)(object)hatchHurtCollider != (Object)null) { hatchHurtCollider.SetActive(true); } } if (hatchAnimationEval >= 0.2f && !hatchCloseImpactPlayed) { hatchCloseImpactPlayed = true; if (soundHatchCloseImpact != null) { soundHatchCloseImpact.Play(HatchSoundPosition, 1f, 1f, 1f, 1f); } } if (stateTimer >= stateTimerMax) { StateSet(RerollState.RollStart); } } private void StateRollStart() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 0.3f; stateTimer = 0f; compartmentAnimationEval = 0f; if ((Object)(object)hatchHurtCollider != (Object)null) { hatchHurtCollider.SetActive(false); } if (soundRollStart != null) { soundRollStart.Play(CompartmentSoundPosition, 1f, 1f, 1f, 1f); } if (!visualOnlyReroll) { DestroyCachedUpgrades(); } ShakeCompartment(); if (meshRotationSpring != null) { AddSpringVelocity(meshRotationSpring, new Vector3(5f, 0f, 0f)); } if (meshPositionSpring != null) { AddSpringVelocity(meshPositionSpring, new Vector3(0f, 2f, 0f)); } stateStart = false; } compartmentAnimationEval = Mathf.Clamp01(stateTimer / stateTimerMax); float num = Evaluate(rollStartShakeCurve, compartmentAnimationEval); ApplyCompartmentRotation(num * 20f); if (stateTimer >= stateTimerMax) { StateSet(RerollState.Rolling); } } private void StateRolling() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 0.5f; stateTimer = 0f; compartmentAnimationEval = 0f; rerollTicksPlayed = 0; finalRollSqueakPlayed = false; if ((Object)(object)rerollCompartmentHurtColliders != (Object)null) { rerollCompartmentHurtColliders.SetActive(true); } if ((Object)(object)rollingParticles != (Object)null) { rollingParticles.Play(true); } if (soundRolling != null) { soundRolling.Play(CompartmentSoundPosition, 1f, 1f, 1f, 1f); } stateStart = false; } compartmentAnimationEval = Mathf.Clamp01(stateTimer / stateTimerMax); float num = Evaluate(rollCurve, compartmentAnimationEval); ApplyCompartmentRotation(num * 360f); float num2 = stateTimerMax / 12f; while (rerollTicksPlayed < 12 && stateTimer >= (float)rerollTicksPlayed * num2) { if (soundRerollTick != null) { Sound val = soundRerollTick; float num3 = rerollTicksPlayed; float num4 = 1f; val.Pitch = num3 / num4; soundRerollTick.Play(CompartmentSoundPosition, 1f, 1f, 1f, 1f); } rerollTicksPlayed++; } if (compartmentAnimationEval >= 0.9f && !finalRollSqueakPlayed) { finalRollSqueakPlayed = true; if (soundFinalRollSqueak != null) { soundFinalRollSqueak.Play(CompartmentSoundPosition, 1f, 1f, 1f, 1f); } } if (stateTimer >= stateTimerMax) { StateSet(RerollState.RollEnd); } } private void StateRollEnd() { //IL_006f: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 0.625f; stateTimer = 0f; compartmentAnimationEval = 0f; if ((Object)(object)rerollCompartmentHurtColliders != (Object)null) { rerollCompartmentHurtColliders.SetActive(false); } if ((Object)(object)rollingParticles != (Object)null) { rollingParticles.Stop(true); } if (soundRollEnd != null) { soundRollEnd.Play(CompartmentSoundPosition, 1f, 1f, 1f, 1f); } if (soundRerollSettle != null) { soundRerollSettle.Play(CompartmentSoundPosition, 1f, 1f, 1f, 1f); } ShakeCompartment(); if (meshRotationSpring != null) { AddSpringVelocity(meshRotationSpring, new Vector3(15f, 0f, 0f)); } if (meshPositionSpring != null) { AddSpringVelocity(meshPositionSpring, new Vector3(0f, 1f, 0f)); } if (maxRerollCount > 0 && rerollCount >= maxRerollCount) { StartBreakBuildUpVisual(); if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { BroadcastBreakBuildUpVisual(); } } stateStart = false; } compartmentAnimationEval = Mathf.Clamp01(stateTimer / stateTimerMax); float num = Evaluate(rollEndShakeCurve, compartmentAnimationEval); ApplyCompartmentRotation(num * 15f); if (stateTimer >= stateTimerMax) { StateSet(RerollState.OpenHatch); } } private void StateOpenHatch() { //IL_006a: 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_009d: Unknown result type (might be due to invalid IL or missing references) if (stateStart) { stateTimerMax = 2f; stateTimer = 0f; hatchAnimationEval = 1f; hatchOpenImpactPlayed = false; if (!visualOnlyReroll) { SpawnPendingReplacements(); } if ((Object)(object)hatchParticles != (Object)null) { hatchParticles.Play(true); } if (soundHatchOpen != null) { soundHatchOpen.Play(HatchSoundPosition, 1f, 1f, 1f, 1f); } if (soundRerollEnd != null) { soundRerollEnd.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f); } ShakeHatch(); stateStart = false; } float num = Mathf.Clamp01(stateTimer / 0.4f); hatchAnimationEval = 1f - num; ApplyHatchClosed(hatchAnimationEval); if (hatchAnimationEval <= 0.7f && (Object)(object)hatchClosed != (Object)null) { hatchClosed.SetActive(false); } if (hatchAnimationEval <= 0.8f && !hatchOpenImpactPlayed) { hatchOpenImpactPlayed = true; if (soundHatchOpenImpact != null) { soundHatchOpenImpact.Play(HatchSoundPosition, 1f, 1f, 1f, 1f); } } if (stateTimer >= 0.4f) { float num2 = Mathf.Clamp01((stateTimer - 0.4f) / 0.2f); SetButtonPositionPressed(1f - num2); FadeBuildUpVisuals(1f - num2); } if (stateTimer >= 0.8f) { buttonRotationTarget = 0f; } if (stateTimer >= stateTimerMax) { cachedUpgrades.Clear(); pendingReplacements.Clear(); if (!visualOnlyReroll && maxRerollCount > 0 && rerollCount >= maxRerollCount) { BreakButton(); BroadcastBroken(); StateSet(RerollState.Broken); } else { StateSet(RerollState.Idle); } } } private void StateWaitingForHost() { if (stateStart) { stateTimerMax = 2f; stateTimer = 0f; stateStart = false; } if (stateTimer >= stateTimerMax) { StateSet(RerollState.Idle); } } private void StateBroken() { if (stateStart) { BreakButton(); stateTimer = 0f; stateTimerMax = 0f; stateStart = false; } } private void StateSet(RerollState nextState) { if (Plugin.DebugLogs.Value && state != nextState && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandReroll.State] {state} -> {nextState}."); } state = nextState; stateStart = true; } internal void ConfigureFromVanilla(UpgradeStand vanillaStand) { scanBox = vanillaStand.upgradeInsideBoxCheck; buttonGrabObject = vanillaStand.buttonGrabObject; buttonRoot = vanillaStand.button; buttonColliderRoot = (((Object)(object)buttonGrabObject != (Object)null) ? buttonGrabObject.colliderTransform : null); hatch = vanillaStand.hatch; upgradeCompartment = vanillaStand.upgradeCompartment; hatchClosed = vanillaStand.hatchClosed; hatchHurtCollider = vanillaStand.hatchHurtCollider; rerollCompartmentHurtColliders = vanillaStand.rerollCompartmentHurtColliders; allMeshesTransform = vanillaStand.allMeshesTransform; interactLocalized = vanillaStand.interactLocalized; hatchParticles = vanillaStand.hatchParticles; rollingParticles = vanillaStand.rollingParticles; buttonPressAnimationCurve = vanillaStand.buttonPressAnimationCurve; buttonDenyCurve = vanillaStand.buttonDenyCurve; hatchAnimationCurve = vanillaStand.hatchAnimationCurve; rollStartShakeCurve = vanillaStand.rollStartShakeCurve; rollCurve = vanillaStand.rollCurve; rollEndShakeCurve = vanillaStand.rollEndShakeCurve; soundButtonPress = vanillaStand.soundButtonPress; soundButtonDeny = vanillaStand.soundButtonDeny; soundHatchClose = vanillaStand.soundHatchClose; soundRollStart = vanillaStand.soundRollStart; soundRolling = vanillaStand.soundRolling; soundRollEnd = vanillaStand.soundRollEnd; soundHatchOpen = vanillaStand.soundHatchOpen; soundButtonTwistUp = vanillaStand.soundButtonTwistUp; soundButtonTwistDown = vanillaStand.soundButtonTwistDown; soundStageBeep = vanillaStand.soundStageBeep; soundStateOn = vanillaStand.soundStateOn; soundStateOff = vanillaStand.soundStateOff; soundRerollStart = vanillaStand.soundRerollStart; soundRerollEnd = vanillaStand.soundRerollEnd; soundRerollTick = vanillaStand.soundRerollTick; soundRerollSettle = vanillaStand.soundRerollSettle; soundFinalRollSqueak = vanillaStand.soundFinalRollSqueak; soundHatchCloseImpact = vanillaStand.soundHatchCloseImpact; soundHatchOpenImpact = vanillaStand.soundHatchOpenImpact; buttonRenderer = vanillaStand.buttonRenderer; buttonNormalMaterial = vanillaStand.buttonNormalMaterial; buttonDenyMaterial = vanillaStand.buttonDenyMaterial; buildUpStages = vanillaStand.buildUpStages; buildUpLight = vanillaStand.buildUpLight; buildUpIntroCurve = vanillaStand.buildUpIntroCurve; buildUpOutroCurve = vanillaStand.buildUpOutroCurve; buttonRubble = vanillaStand.buttonRubble; fireHurtCollider = vanillaStand.fireHurtCollider; fireLight = vanillaStand.fireLight; particleButtonBreak = vanillaStand.particleButtonBreak; particleFireLoop = vanillaStand.particleFireLoop; buildUpParticles = vanillaStand.buildUpParticles; soundButtonBreak = vanillaStand.soundButtonBreak; soundBuildUpLoop = vanillaStand.soundBuildUpLoop; flickerFadeLightCurve = vanillaStand.flickerFadeLightCurve; meshRotationSpring = vanillaStand.meshRotationSpring; meshPositionSpring = vanillaStand.meshPositionSpring; buttonRotationSpring = vanillaStand.buttonRotationSpring; soundFluorescentLightTurnOff = vanillaStand.soundFluorescentLightTurnOff; soundLilButtonFire = vanillaStand.soundLilButtonFire; if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandReroll.Binding] Copied vanilla references. vanilla=" + ((Object)vanillaStand).name + ", scanBox=" + NameOrNull(scanBox) + ", button=" + NameOrNull(buttonRoot) + ", hatch=" + NameOrNull(hatch) + ", compartment=" + NameOrNull(upgradeCompartment) + ", " + $"buildUpStages={((buildUpStages != null) ? buildUpStages.Length : 0)}.")); } } private float ComputeChargingButtonTarget(float elapsed) { int num = Mathf.Max(1, buildUpStages.Length); return (float)Mathf.Clamp(Mathf.FloorToInt(elapsed / ChargeStageDuration) + 1, 0, num) * buttonStageRotationAngle; } private void SyncChargeStageTriggers(float elapsed) { if (chargeStageTriggered == null || chargeStageTriggered.Length != buildUpStages.Length) { chargeStageTriggered = new bool[buildUpStages.Length]; } for (int i = 0; i < chargeStageTriggered.Length; i++) { chargeStageTriggered[i] = elapsed >= (float)i * ChargeStageDuration; } } private void ApplyChargeVisualsSilent(float elapsed) { if (buildUpStages != null && buildUpStages.Length != 0) { buttonRotationTarget = ComputeChargingButtonTarget(elapsed); for (int i = 0; i < buildUpStages.Length; i++) { float num = (float)i * ChargeStageDuration; float num2 = Mathf.Clamp01((elapsed - num) / ChargeStageDuration); float value = (SemiFunc.Photosensitivity() ? num2 : Evaluate(buildUpIntroCurve, num2)); ApplyStageEmission(buildUpStages[i], value); } UpdateBuildUpLight(elapsed); } } private void BeginRollbackStage(int stageIndex) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) if (buildUpStages == null || buildUpStages.Length == 0) { rollbackCurrentStage = -1; return; } rollbackCurrentStage = Mathf.Clamp(stageIndex, 0, buildUpStages.Length - 1); rollbackCurrentStageElapsed = 0f; BuildUpStage val = buildUpStages[rollbackCurrentStage]; rollbackCurrentStageStartEmission = ((rollbackCurrentStage == rollbackTopStage) ? Mathf.Clamp01(GetStageIntroValue(rollbackCurrentStage, chargeElapsed)) : 1f); if ((Object)(object)buildUpLight != (Object)null) { rollbackCurrentStageStartLightIntensity = buildUpLight.intensity; rollbackCurrentStageStartLightColor = buildUpLight.color; } else { rollbackCurrentStageStartLightIntensity = 0f; rollbackCurrentStageStartLightColor = Color.black; } if (rollbackCurrentStage == 0) { rollbackCurrentStageEndLightIntensity = 0f; rollbackCurrentStageEndLightColor = val.stageColor; } else { BuildUpStage val2 = buildUpStages[rollbackCurrentStage - 1]; rollbackCurrentStageEndLightIntensity = val2.lightIntensity; rollbackCurrentStageEndLightColor = val2.stageColor; } buttonRotationTarget = (float)rollbackCurrentStage * buttonStageRotationAngle; if (soundStageBeep != null) { soundStageBeep.Pitch = Mathf.Lerp(0.8f, 1.4f, (float)rollbackCurrentStage / Mathf.Max(1f, (float)buildUpStages.Length - 1f)); soundStageBeep.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f); } if (soundStateOff != null) { soundStateOff.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f); } if (soundButtonTwistDown != null) { soundButtonTwistDown.Pitch = 1f + (float)rollbackCurrentStage * 0.2f; soundButtonTwistDown.Play(ButtonSoundPosition, 1f, 1f, 1f, 1f); } } private void ApplyRollbackStageVisuals(float eased) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (rollbackCurrentStage >= 0 && buildUpStages != null && rollbackCurrentStage < buildUpStages.Length) { float num = 1f - Mathf.Clamp01(eased); ApplyStageEmission(buildUpStages[rollbackCurrentStage], rollbackCurrentStageStartEmission * num); if ((Object)(object)buildUpLight != (Object)null) { buildUpLight.intensity = Mathf.Lerp(rollbackCurrentStageEndLightIntensity, rollbackCurrentStageStartLightIntensity, num); buildUpLight.color = Color.Lerp(rollbackCurrentStageEndLightColor, rollbackCurrentStageStartLightColor, num); } chargeElapsed = (float)rollbackCurrentStage * ChargeStageDuration + ChargeStageDuration * rollbackCurrentStageStartEmission * num; } } private float GetStageIntroValue(int stageIndex, float elapsed) { float num = (float)stageIndex * ChargeStageDuration; if (elapsed < num) { return 0f; } float num2 = Mathf.Clamp01((elapsed - num) / ChargeStageDuration); if (!SemiFunc.Photosensitivity()) { return Evaluate(buildUpIntroCurve, num2); } return num2; } private void ResumeChargingFromRollback(int stageJustRolledBack) { chargeElapsed = (float)stageJustRolledBack * ChargeStageDuration; if (chargeStageTriggered == null || chargeStageTriggered.Length != buildUpStages.Length) { chargeStageTriggered = new bool[buildUpStages.Length]; } for (int i = 0; i < chargeStageTriggered.Length; i++) { chargeStageTriggered[i] = i < stageJustRolledBack; } rollbackResumeRequested = false; resumeChargeFromRollback = true; StateSet(RerollState.Holding); if (Plugin.DebugLogs.Value && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)($"[UpgradeStandReroll.State] Resume from rollback stage={stageJustRolledBack}, " + $"chargeElapsed={chargeElapsed:0.00}.")); } } private void ResetChargeStageTriggers() { if (chargeStageTriggered == null || chargeStageTriggered.Length != buildUpStages.Length) { chargeStageTriggered = new bool[buildUpStages.Length]; } for (int i = 0; i < chargeStageTriggered.Length; i++) { chargeStageTriggered[i] = false; } } private void UpdateChargeVisuals(float elapsed) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) buttonRotationTarget = ComputeChargingButtonTarget(elapsed); for (int i = 0; i < buildUpStages.Length; i++) { float num = (float)i * 0.3f; if (elapsed < num) { continue; } if (!chargeStageTriggered[i]) { chargeStageTriggered[i] = true; if (soundStageBeep != null) { soundStageBeep.Pitch = Mathf.Lerp(0.8f, 1.4f, (float)i / Mathf.Max(1f, (float)buildUpStages.Length - 1f)); soundStageBeep.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f); } if (soundStateOn != null) { soundStateOn.Play(((Component)this).transform.position, 1f, 1f, 1f, 1f); } if (soundButtonTwistUp != null) { soundButtonTwistUp.Pitch = 1f + (float)i * 0.2f; soundButtonTwistUp.Play(ButtonSoundPosition, 1f, 1f, 1f, 1f); } } float value = Mathf.Clamp01((elapsed - num) / 0.3f); ApplyStageEmission(buildUpStages[i], Evaluate(buildUpIntroCurve, value)); } UpdateBuildUpLight(elapsed); } private void FadeBuildUpVisuals(float value) { if (buildUpStages != null) { BuildUpStage[] array = buildUpStages; foreach (BuildUpStage stageInfo in array) { ApplyStageEmission(stageInfo, value); } } if ((Object)(object)buildUpLight != (Object)null) { buildUpLight.intensity = Mathf.Lerp(0f, 1f, Mathf.Clamp01(value)); if (value <= 0f) { ((Component)buildUpLight).gameObject.SetActive(false); } } } private void ApplyStageEmission(BuildUpStage stageInfo, float value) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) if (stageInfo?.emissionMeshes == null) { return; } Color val = Color.Lerp(Color.black, stageInfo.stageColor, Mathf.Clamp01(value)); MeshRenderer[] emissionMeshes = stageInfo.emissionMeshes; foreach (MeshRenderer val2 in emissionMeshes) { if (!((Object)(object)val2 == (Object)null)) { Material material = ((Renderer)val2).material; material.EnableKeyword("_EMISSION"); material.SetColor("_EmissionColor", val); } } } private void UpdateBuildUpLight(float elapsed) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)buildUpLight == (Object)null) && buildUpStages != null && buildUpStages.Length != 0) { ((Component)buildUpLight).gameObject.SetActive(true); int num = Mathf.Clamp(Mathf.FloorToInt(elapsed / 0.3f), 0, buildUpStages.Length - 1); buildUpLight.intensity = buildUpStages[num].lightIntensity; buildUpLight.color = buildUpStages[num].stageColor; } } private void ResetBuildUpVisuals() { if (buildUpStages != null) { BuildUpStage[] array = buildUpStages; foreach (BuildUpStage stageInfo in array) { ApplyStageEmission(stageInfo, 0f); } } if ((Object)(object)buildUpLight != (Object)null) { buildUpLight.intensity = 0f; ((Component)buildUpLight).gameObject.SetActive(false); } if ((Object)(object)buildUpParticles != (Object)null) { buildUpParticles.Stop(true); } } private void StartBreakBuildUpVisual() { if (!isBroken) { buildUpActive = true; buildUpTimer = 0f; if (!SemiFunc.Photosensitivity() && (Object)(object)buildUpParticles != (Object)null) { buildUpParticles.Play(true); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Visuals] Break build-up visual started."); } } } private void UpdateBuildUpLoop() { if (buildUpActive && soundBuildUpLoop != null) { buildUpTimer += Time.deltaTime; float num = Mathf.Clamp01(buildUpTimer / 1.025f); float num2 = Mathf.Lerp(1f, 4f, num); float num3 = Mathf.Lerp(0f, 0.6f, num); soundBuildUpLoop.PlayLoop(true, 100f, 100f, num2, num3); } } private void ApplyButtonRotation() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)buttonRoot == (Object)null)) { buttonRoot.localRotation = buttonOriginalRotation * Quaternion.Euler(0f, buttonRotationAngle, 0f); } } private void UpdateButtonRotationSpring() { if (buttonRotationSpring == null) { buttonRotationAngle = Mathf.Lerp(buttonRotationAngle, buttonRotationTarget, Time.deltaTime * 14f); } else { buttonRotationAngle = SemiFunc.SpringFloatGet(buttonRotationSpring, buttonRotationTarget, -1f); } } private void UpdateMeshSprings() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)allMeshesTransform == (Object)null) && meshRotationSpring != null && meshPositionSpring != null) { RerollState rerollState = state; if ((uint)(rerollState - 6) <= 2u) { float num = Time.deltaTime * 10f; float num2 = Time.deltaTime * 2f; AddSpringVelocity(meshRotationSpring, new Vector3(Random.Range(-4f, 4f), Random.Range(-4f, 4f), Random.Range(-4f, 4f)) * num); AddSpringVelocity(meshPositionSpring, new Vector3(Random.Range(-0.8f, 0.8f), Random.Range(-0.8f, 0.8f), Random.Range(-0.8f, 0.8f)) * num2); } allMeshesTransform.localRotation = SemiFunc.SpringQuaternionGet(meshRotationSpring, allMeshesOriginalRotation, -1f); allMeshesTransform.localPosition = SemiFunc.SpringVector3Get(meshPositionSpring, allMeshesOriginalPosition, -1f); } } private static void AddSpringVelocity(SpringQuaternion spring, Vector3 delta) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (spring != null && !(SpringQuaternionVelocityField == null)) { Vector3 val = (Vector3)SpringQuaternionVelocityField.GetValue(spring); SpringQuaternionVelocityField.SetValue(spring, val + delta); } } private static void AddSpringVelocity(SpringVector3 spring, Vector3 delta) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (spring != null && !(SpringVector3VelocityField == null)) { Vector3 val = (Vector3)SpringVector3VelocityField.GetValue(spring); SpringVector3VelocityField.SetValue(spring, val + delta); } } private void SetButtonPositionPressed(float value) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)buttonRoot == (Object)null)) { buttonRoot.localPosition = new Vector3(buttonOriginalPosition.x, buttonOriginalPosition.y - 0.06f * Mathf.Clamp01(value), buttonOriginalPosition.z); } } private void ApplyHatchClosed(float closedValue) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)hatch == (Object)null)) { float num = Evaluate(hatchAnimationCurve, Mathf.Clamp01(closedValue)); hatch.localPosition = new Vector3(hatchOriginalPosition.x, Mathf.Lerp(-0.714f, -0.146f, num), hatchOriginalPosition.z); hatch.localScale = new Vector3(hatchOriginalScale.x, Mathf.Lerp(0.655f, 1f, num), hatchOriginalScale.z); } } private void ApplyCompartmentRotation(float xAngle) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //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) if ((Object)(object)upgradeCompartment != (Object)null) { upgradeCompartment.localRotation = compartmentOriginalRotation * Quaternion.Euler(xAngle, 0f, 0f); } } private void BreakButton() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) isBroken = true; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandReroll.Visuals] Button broken visual activated."); } if ((Object)(object)particleButtonBreak != (Object)null) { particleButtonBreak.Play(true); } if ((Object)(object)particleFireLoop != (Object)null) { particleFireLoop.Play(true); } if (soundButtonBreak != null) { soundButtonBreak.Play(ButtonSoundPosition, 1f, 1f, 1f, 1f); } buildUpActive = false; if (soundBuildUpLoop != null) { soundBuildUpLoop.Stop(); } if ((Object)(object)buttonRenderer != (Object)null) { ((Renderer)buttonRenderer).enabled = false; } fireActive = true; fireLightFadeInTimer = 0f; firePerlinOffsetX = Random.Range(0f, 100f); firePerlinOffsetY = Random.Range(0f, 100f); if ((Object)(object)buttonRoot != (Object)null && ((Object)(object)buttonRubble == (Object)null || !buttonRubble.transform.IsChildOf(buttonRoot))) { ((Component)buttonRoot).gameObject.SetActive(false); } if ((Object)(object)buttonGrabObject != (Object)null) { if ((Object)(object)buttonRubble == (Object)null || !buttonRubble.transform.IsChildOf(((Component)buttonGrabObject).transform)) { ((Component)buttonGrabObject).gameObject.SetActive(false); } else { ((Behaviour)buttonGrabObject).enabled = false; } } if ((Object)(object)buttonRubble != (Object)null) { buttonRubble.SetActive(true); } if ((Object)(object)fireHurtCollider != (Object)null) { fireHurtCollider.SetActive(true); } if ((Object)(object)fireLight != (Object)null) { ((Component)fireLight).gameObject.SetActive(true); ((Behaviour)fireLight).enabled = true; fireLight.intensity = 1f; } ResetBuildUpVisuals(); } private void UpdateFire() { if (!fireActive) { return; } if (soundLilButtonFire != null) { soundLilButtonFire.PlayLoop(true, 3f, 3f, 1f, 1f); } if ((Object)(object)fireLight != (Object)null) { if (fireLightFadeInTimer < 0.35f) { fireLightFadeInTimer += Time.deltaTime; } float num = Mathf.Clamp01(fireLightFadeInTimer / 0.35f); float num2 = Mathf.PerlinNoise(Time.time * 9f + firePerlinOffsetX, firePerlinOffsetY); fireLight.intensity = Mathf.Lerp(1f, 1.6f, num2) * num; } } private void SetButtonNormal() { if ((Object)(object)buttonRenderer != (Object)null && (Object)(object)buttonNormalMaterial != (Object)null) { ((Renderer)buttonRenderer).enabled = true; ((Renderer)buttonRenderer).material = buttonNormalMaterial; } } private void SetButtonDeny() { if ((Object)(object)buttonRenderer != (Object)null && (Object)(object)buttonDenyMaterial != (Object)null) { ((Renderer)buttonRenderer).material = buttonDenyMaterial; } } private void ShakeButton() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)GameDirector.instance == (Object)null) && !((Object)(object)buttonRoot == (Object)null)) { GameDirector.instance.CameraImpact.ShakeDistance(2f, 3f, 8f, buttonRoot.position, 0.1f); GameDirector.instance.CameraShake.ShakeDistance(2f, 3f, 8f, buttonRoot.position, 0.1f); } } private void ShakeHatch() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)GameDirector.instance == (Object)null) && !((Object)(object)hatch == (Object)null)) { GameDirector.instance.CameraImpact.ShakeDistance(3f, 3f, 8f, hatch.position, 0.1f); GameDirector.instance.CameraShake.ShakeDistance(3f, 3f, 8f, hatch.position, 0.1f); } } private void ShakeCompartment() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)GameDirector.instance == (Object)null) && !((Object)(object)upgradeCompartment == (Object)null)) { GameDirector.instance.CameraImpact.ShakeDistance(3f, 3f, 8f, upgradeCompartment.position, 0.1f); GameDirector.instance.CameraShake.ShakeDistance(3f, 3f, 8f, upgradeCompartment.position, 0.1f); } } private static float Evaluate(AnimationCurve curve, float value) { if (curve != null) { return curve.Evaluate(Mathf.Clamp01(value)); } return Mathf.Clamp01(value); } } } namespace MoreStandsForShops.Spawners { public static class DroneCrystalStandSpawner { private const string CosmeticModuleName = "Level Generator/Level/Module - Shop - S - Cosmetic Machine 01(Clone)"; private const string CandyShelf2Name = "Candy Shelf 2"; private static readonly Vector3 ShelfLocalPosition = new Vector3(2.04f, 0.03f, -5.475f); private const float ShelfLocalYaw = 270f; private static readonly string[] KnownHealthShelfPaths = new string[3] { "Level Generator/Level/Module - Shop - N - Middle Stands(Clone)/ITEM STANDS/valuable shelf short (1)", "Level Generator/Level/Module - Shop - N - Center Extract(Clone)/ITEM STANDS/valuable shelf short (1)", "Level Generator/Level/Module - Shop - N - Corner Stands(Clone)/ITEM STANDS/valuable shelf short (1)" }; private static GameObject _cachedPrefab; private static bool _prefabPrepared; public static bool EnsurePrefabPrepared() { if (!_prefabPrepared) { return PreparePrefab(); } return true; } public static bool TrySpawn(out GameObject spawnedStand, bool configureItemVolumes = true) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) spawnedStand = null; spawnedStand = FindExistingSpawnedStand(); if ((Object)(object)spawnedStand != (Object)null) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[DroneCrystalStandSpawner] Drone/Crystal stand already exists; skipping duplicate spawn."); } return true; } Transform val = FindTransformByPath("Level Generator/Level/Module - Shop - S - Cosmetic Machine 01(Clone)"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"[DroneCrystalStandSpawner] Cosmetic Machine module not found."); return false; } Transform val2 = val.Find("---- Level ------------/PROPS"); Transform val3 = ((val2 != null) ? val2.Find("Candy Shelf 2") : null); if ((Object)(object)val3 == (Object)null) { Plugin.Log.LogWarning((object)"[DroneCrystalStandSpawner] Candy Shelf 2 not found in Cosmetic Machine."); return false; } if (!_prefabPrepared && !PreparePrefab()) { return false; } Vector3 val4 = val.TransformPoint(ShelfLocalPosition); Quaternion val5 = val.rotation * Quaternion.Euler(0f, 270f, 0f); if (!IsAgainstWall(val4, val5)) { Plugin.Log.LogWarning((object)"[DroneCrystalStandSpawner] Position not against a wall."); return false; } List list = new List(); if (!PrepareArea(val4, val5, val3, list)) { Plugin.Log.LogWarning((object)"[DroneCrystalStandSpawner] Area preparation failed."); return false; } spawnedStand = Object.Instantiate(_cachedPrefab, val4, val5); ((Object)spawnedStand).name = "MoreStandsForShops Drone Crystal Stand"; spawnedStand.SetActive(true); spawnedStand.transform.SetParent(val2, true); ((Component)val3).gameObject.SetActive(false); list.Add(GetTransformPath(val3)); if (configureItemVolumes) { ItemVolumeHelper.AssignVolumesForDroneCrystalStand(spawnedStand); } else { DisableItemVolumes(spawnedStand); } if (configureItemVolumes && SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { ShopLayoutSync.SetDroneCrystalShelf(new DroneCrystalShelfLayout { Enabled = true, DroneSlotCount = (Plugin.ItemCounts.TryGetValue("Drones", out var value) ? value.Value : 0), CrystalSlotCount = (Plugin.ItemCounts.TryGetValue("Power Crystals", out var value2) ? value2.Value : 0), DisabledPaths = list.ToArray() }); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[DroneCrystalStandSpawner] Drone/Crystal stand spawned successfully. itemVolumes={configureItemVolumes}, disabled={list.Count}."); } return true; } public static bool SpawnNetworkVisual(string spawnId, string[] disabledPaths) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (!EnsurePrefabPrepared()) { return false; } if ((Object)(object)FindExistingSpawnedStand() != (Object)null) { return true; } Transform val = FindTransformByPath("Level Generator/Level/Module - Shop - S - Cosmetic Machine 01(Clone)"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"[DroneCrystalStandSpawner] Network visual skipped: Cosmetic Machine module not found."); return false; } Transform val2 = val.Find("---- Level ------------/PROPS"); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[DroneCrystalStandSpawner] Network visual skipped: PROPS root not found."); return false; } Vector3 val3 = val.TransformPoint(ShelfLocalPosition); Quaternion val4 = val.rotation * Quaternion.Euler(0f, 270f, 0f); ScenePathUtility.DisableExactPaths(disabledPaths, "[DroneCrystalStandSpawner:Network]"); GameObject obj = Object.Instantiate(_cachedPrefab, val3, val4); ((Object)obj).name = "MoreStandsForShops Drone Crystal Stand"; obj.SetActive(true); obj.transform.SetParent(val2, true); DisableItemVolumes(obj); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[DroneCrystalStandSpawner] Network visual spawned: id=" + spawnId + ", parent=" + GetTransformPath(val2) + ".")); } return true; } private static GameObject FindExistingSpawnedStand() { return (from t in ShopSceneCache.Current.Transforms where (Object)(object)t != (Object)null && ((Component)t).gameObject.activeInHierarchy where ((Object)t).name.StartsWith("MoreStandsForShops Drone Crystal Stand", StringComparison.OrdinalIgnoreCase) select ((Component)t).gameObject).FirstOrDefault(); } private static bool PreparePrefab() { Transform val = FindHealthShelfVisual(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"[DroneCrystalStandSpawner] No vanilla health shelf visual found."); return false; } _cachedPrefab = Object.Instantiate(((Component)val).gameObject); ((Object)_cachedPrefab).name = "MoreStandsForShops_DroneCrystalStand_Prefab"; _cachedPrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_cachedPrefab); PhotonView component = _cachedPrefab.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } _prefabPrepared = true; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[DroneCrystalStandSpawner] Drone/Crystal stand prefab prepared."); } return true; } private static Transform FindHealthShelfVisual() { string[] knownHealthShelfPaths = KnownHealthShelfPaths; for (int i = 0; i < knownHealthShelfPaths.Length; i++) { Transform val = FindTransformByPath(knownHealthShelfPaths[i]); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy && ((Component)val).GetComponentsInChildren(true).Length != 0) { return val; } } return (from t in ShopSceneCache.Current.Transforms where (Object)(object)t != (Object)null && ((Component)t).gameObject.activeInHierarchy where string.Equals(((Object)t).name, "valuable shelf short (1)", StringComparison.OrdinalIgnoreCase) where GetTransformPath(t).IndexOf("/ITEM STANDS/", StringComparison.OrdinalIgnoreCase) >= 0 select t).FirstOrDefault((Func)((Transform t) => ((Component)t).GetComponentsInChildren(true).Length != 0)); } private static void DisableItemVolumes(GameObject stand) { ItemVolume[] componentsInChildren = stand.GetComponentsInChildren(true); foreach (ItemVolume val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { ((Behaviour)val).enabled = false; ((Component)val).gameObject.SetActive(false); } } } private static bool IsAgainstWall(Vector3 position, Quaternion rotation) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4] { rotation * Vector3.forward, rotation * Vector3.back, rotation * Vector3.right, rotation * Vector3.left }; float num = 0.5f; LayerMask val = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "Default" })); Vector3[] array2 = array; RaycastHit val3 = default(RaycastHit); foreach (Vector3 val2 in array2) { if (Physics.Raycast(position + Vector3.up * 0.5f, val2, ref val3, 2f, LayerMask.op_Implicit(val), (QueryTriggerInteraction)1) && Mathf.Abs(((RaycastHit)(ref val3)).normal.y) < 0.1f && ((RaycastHit)(ref val3)).distance <= num) { return true; } } return false; } private static bool PrepareArea(Vector3 position, Quaternion rotation, Transform candyShelf2, List disabledObjects) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0.85f, 1.1f, 0.55f); Collider[] array = Physics.OverlapBox(position + Vector3.up * val.y, val, rotation, -1, (QueryTriggerInteraction)1); foreach (Collider val2 in array) { if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).transform == (Object)null || (Object)(object)((Component)val2).transform == (Object)(object)candyShelf2 || ((Component)val2).transform.IsChildOf(candyShelf2) || ((Object)((Component)val2).transform).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase)) { continue; } string text = GetTransformPath(((Component)val2).transform).ToLowerInvariant(); if (text.Contains("/walls/") || text.Contains("/floor") || text.Contains("/ceiling") || text.Contains("collider") || text.Contains("trigger")) { continue; } if (IsProtected(((Component)val2).transform)) { Plugin.Log.LogWarning((object)("[DroneCrystalStandSpawner] Protected object blocks spawn: " + ((Object)((Component)val2).transform).name)); return false; } if (IsProtected(((Component)val2).transform)) { continue; } Transform val3 = FindDecorativeDisableRoot(((Component)val2).transform); if (!((Object)(object)val3 == (Object)null) && !IsProtected(val3) && !IsUnsafeDisableRoot(val3)) { ((Component)val3).gameObject.SetActive(false); disabledObjects.Add(GetTransformPath(val3)); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[DroneCrystalStandSpawner] Disabled: " + GetTransformPath(val3))); } } } return true; } private static bool IsProtected(Transform t) { string text = GetTransformPath(t).ToLowerInvariant(); string[] array = new string[16] { "cash register", "cashier", "cashiers desk", "shop owner", "shopkeeper", "upgrade stand", "health stand", "revive stand", "battery upgrade stand", "item stands", "valuable shelf", "weapon stand", "weapon shelf", "window shop", "extraction", "truck" }; foreach (string value in array) { if (text.Contains(value)) { return true; } } if ((Object)(object)((Component)t).GetComponentInChildren(true) != (Object)null) { return true; } if ((Object)(object)((Component)t).GetComponentInParent(true) != (Object)null) { return true; } return false; } private static bool IsUnsafeDisableRoot(Transform transform) { string text = GetTransformPath(transform).ToLowerInvariant(); string text2 = ((Object)transform).name.ToLowerInvariant(); if (!text.Contains("/dependencies/")) { switch (text2) { default: if (!text2.Contains("---- level") && !text2.StartsWith("module - shop") && !(text2 == "level")) { return text2 == "level generator"; } break; case "props": case "items": case "item stands": case "dependencies": break; } } return true; } private static Transform FindDecorativeDisableRoot(Transform transform) { for (Transform val = transform; (Object)(object)val != (Object)null && (Object)(object)val.parent != (Object)null; val = val.parent) { string text = ((Object)val.parent).name.ToLowerInvariant(); switch (text) { default: if (!text.Contains("---- level") && !text.StartsWith("module - shop")) { continue; } break; case "props": case "items": case "item stands": case "dependencies": break; } return val; } return transform; } private static Transform FindTransformByPath(string path) { return ScenePathUtility.FindTransformByPath(path); } private static string GetTransformPath(Transform t) { return ShopSceneCache.Current.GetTransformPath(t); } } public static class UpgradeStandSpawner { private sealed class UpgradeVolumeSource { internal readonly ItemVolume Volume; internal readonly Vector3 LocalPosition; internal readonly Quaternion LocalRotation; internal readonly Vector3 LocalScale; internal readonly float Distance; internal readonly string Path; internal UpgradeVolumeSource(ItemVolume volume, Transform originalStand) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) Volume = volume; LocalPosition = originalStand.InverseTransformPoint(((Component)volume).transform.position); LocalRotation = Quaternion.Inverse(originalStand.rotation) * ((Component)volume).transform.rotation; LocalScale = ((Component)volume).transform.localScale; Distance = Vector3.Distance(originalStand.position, ((Component)volume).transform.position); Path = GetTransformPath(((Component)volume).transform); } } [CompilerGenerated] private sealed class d__13 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Vector3 position; public Quaternion rotation; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00b3: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 1; return true; case 1: <>1__state = -1; MoveCartOverlaps(position, rotation); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; case 2: <>1__state = -1; MoveCartOverlaps(position, rotation); <>2__current = (object)new WaitForSeconds(2f); <>1__state = 3; return true; case 3: <>1__state = -1; MoveCartOverlaps(position, rotation); <>2__current = (object)new WaitForSeconds(4f); <>1__state = 4; return true; case 4: <>1__state = -1; MoveCartOverlaps(position, rotation); <>2__current = (object)new WaitForSeconds(7f); <>1__state = 5; return true; case 5: <>1__state = -1; MoveCartOverlaps(position, rotation); 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(); } } [CompilerGenerated] private sealed class d__9 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Vector3 position; public Quaternion rotation; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0043: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 1; return true; case 1: <>1__state = -1; DisableMagazineDisplaysAt(position, rotation); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; case 2: <>1__state = -1; DisableMagazineDisplaysAt(position, rotation); 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(); } } [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string[] paths; public string logPrefix; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 1; return true; case 1: <>1__state = -1; ScenePathUtility.DisableExactPaths(paths, logPrefix); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; case 2: <>1__state = -1; ScenePathUtility.DisableExactPaths(paths, logPrefix); 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(); } } private static GameObject _cachedPrefab; private static bool _prefabPrepared; private static readonly RaycastHit[] WallHits = (RaycastHit[])(object)new RaycastHit[16]; public static bool EnsurePrefabPrepared() { if (!_prefabPrepared) { return PreparePrefab(); } return true; } public static bool TrySpawn(out GameObject spawnedStand, bool configureItemVolumes = true) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: 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_032d: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) spawnedStand = null; if (!Plugin.EnableAdditionalUpgradeStand.Value) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandSpawner] Disabled in config."); } return false; } spawnedStand = FindExistingSpawnedStand(); if ((Object)(object)spawnedStand != (Object)null) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandSpawner] Additional upgrade stand already exists; skipping duplicate spawn."); } return true; } if (!_prefabPrepared && !PreparePrefab()) { return false; } bool flag = IsPaintingSecretShopPresent(); foreach (SpawnPointData item in (from point in CleanPresetDatabase.GetSpawnPoints() orderby point.SourceCount descending select point).ToList()) { Transform val = FindTransformByPath(item.MainModule); if ((Object)(object)val == (Object)null) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandSpawner] Module '" + item.MainModule + "' not found.")); } continue; } Vector3 val2 = val.TransformPoint(item.LocalPosition); Quaternion val3 = val.rotation * Quaternion.Euler(0f, item.LocalYaw, 0f); if (!IsAgainstWall(val2, val3)) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Variant '{item.VariantId}' rejected: no back wall within 0.5m. local={item.LocalPosition}, world={val2}, yaw={item.LocalYaw}, sourceCount={item.SourceCount}."); } continue; } if (ScenePathUtility.HasActivePath(item.RejectIfPresentPaths, out var activePath)) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Variant '{item.VariantId}' rejected: preset protected path is active '{activePath}'. local={item.LocalPosition}, world={val2}, yaw={item.LocalYaw}, sourceCount={item.SourceCount}."); } continue; } if (HasProtectedOverlap(val2, val3, flag, out var objectName)) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Variant '{item.VariantId}' rejected: protected overlap '{objectName}'. local={item.LocalPosition}, world={val2}, yaw={item.LocalYaw}, sourceCount={item.SourceCount}."); } continue; } List list = ScenePathUtility.DisableExactPaths(item.DisablePaths, "[UpgradeStandSpawner]"); list.AddRange(DisableMovableOverlaps(val2, val3)); spawnedStand = Object.Instantiate(_cachedPrefab, val2, val3); ((Object)spawnedStand).name = "MoreStandsForShops Upgrade Stand"; spawnedStand.SetActive(true); spawnedStand.transform.SetParent(val, true); if (configureItemVolumes) { ConfigureUpgradeVolumes(spawnedStand); } else { DisableItemVolumes(spawnedStand); } if (configureItemVolumes && SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { ShopLayoutSync.SetUpgradeStand(new UpgradeStandLayout { Enabled = true, VariantId = item.VariantId, Position = val2, Rotation = val3, ParentPath = ScenePathUtility.GetTransformPath(val), DisabledPaths = list.ToArray(), UpgradeSlotCount = (Plugin.ItemCounts.TryGetValue("Upgrades Per Stand", out var value) ? value.Value : 14) }); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Successfully spawned additional upgrade stand: variant={item.VariantId}, sourceCount={item.SourceCount}, main={item.MainModule}, local={item.LocalPosition}, world={val2}, yaw={item.LocalYaw}, itemVolumes={configureItemVolumes}, disabled={list.Count}, protectPainting={flag}."); } SchedulePresetBlockerRecheck(item.DisablePaths, "[UpgradeStandSpawner:Delayed]"); ScheduleMagazineDisplayRecheck(val2, val3); ScheduleCartOverlapRecheck(val2, val3); return true; } Plugin.Log.LogWarning((object)"[UpgradeStandSpawner] No valid spawn point found."); return false; } public static bool SpawnNetworkVisual(string spawnId, string variantId, Vector3 position, Quaternion rotation, string parentPath, string[] disabledPaths) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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) if (!EnsurePrefabPrepared()) { return false; } if ((Object)(object)FindExistingSpawnedStand() != (Object)null) { return true; } Transform val = ScenePathUtility.FindTransformByPath(parentPath); if ((Object)(object)val == (Object)null) { return false; } ScenePathUtility.DisableExactPaths(disabledPaths, "[UpgradeStandSpawner:Network]"); GameObject obj = Object.Instantiate(_cachedPrefab, position, rotation); ((Object)obj).name = "MoreStandsForShops Upgrade Stand " + variantId; obj.SetActive(true); obj.transform.SetParent(val, true); DisableItemVolumes(obj); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandSpawner] Network visual spawned: id=" + spawnId + ", variant=" + variantId + ", parent=" + parentPath + ".")); } SchedulePresetBlockerRecheck(disabledPaths, "[UpgradeStandSpawner:NetworkDelayed]"); ScheduleMagazineDisplayRecheck(position, rotation); return true; } private static void SchedulePresetBlockerRecheck(IEnumerable paths, string logPrefix) { if (!((Object)(object)Plugin.Instance == (Object)null) && paths != null) { string[] array = paths.Where((string path) => !string.IsNullOrWhiteSpace(path)).Distinct().ToArray(); if (array.Length != 0) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(RecheckPresetBlockersRoutine(array, logPrefix)); } } } [IteratorStateMachine(typeof(d__7))] private static IEnumerator RecheckPresetBlockersRoutine(string[] paths, string logPrefix) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { paths = paths, logPrefix = logPrefix }; } private static void ScheduleMagazineDisplayRecheck(Vector3 position, Quaternion rotation) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Plugin.Instance == (Object)null)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(RecheckMagazineDisplaysRoutine(position, rotation)); } } [IteratorStateMachine(typeof(d__9))] private static IEnumerator RecheckMagazineDisplaysRoutine(Vector3 position, Quaternion rotation) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(0) { position = position, rotation = rotation }; } private static void DisableMagazineDisplaysAt(Vector3 position, Quaternion rotation) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(1.15f, 1.15f, 0.75f); Vector3 center = position + Vector3.up * val.y; DisableMagazineDisplaysInsideStand(disabledTargets: new HashSet(), disabledPaths: new List(), standBounds: BuildMagazineCleanupBounds(center, val, rotation)); } private static void ScheduleCartOverlapRecheck(Vector3 position, Quaternion rotation) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Plugin.Instance == (Object)null) && SemiFunc.IsMasterClientOrSingleplayer()) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(RecheckCartOverlapsRoutine(position, rotation)); } } public static void SchedulePostPopulateCartOverlapRecheck() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Plugin.Instance == (Object)null) && SemiFunc.IsMasterClientOrSingleplayer()) { GameObject val = FindExistingSpawnedStand(); if (!((Object)(object)val == (Object)null)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(RecheckCartOverlapsRoutine(val.transform.position, val.transform.rotation)); } } } [IteratorStateMachine(typeof(d__13))] private static IEnumerator RecheckCartOverlapsRoutine(Vector3 position, Quaternion rotation) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0) { position = position, rotation = rotation }; } private static GameObject FindExistingSpawnedStand() { return (from t in Resources.FindObjectsOfTypeAll() where (Object)(object)t != (Object)null && ((Component)t).gameObject.activeInHierarchy where ((Object)t).name.StartsWith("MoreStandsForShops Upgrade Stand", StringComparison.OrdinalIgnoreCase) select ((Component)t).gameObject).FirstOrDefault(); } private static void ConfigureUpgradeVolumes(GameObject spawnedStand) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) ConfigEntry value; int num = (Plugin.ItemCounts.TryGetValue("Upgrades Per Stand", out value) ? value.Value : 14); ItemVolume[] array = GetStandItemVolumes(spawnedStand); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Clone child ItemVolume count before source copy: {array.Length}."); } if (array.Length < num && num > 0) { if (array.Length != 0) { DisableExistingUpgradeVolumeChildren(array); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Disabled {array.Length} incomplete cloned upgrade ItemVolume(s) before vanilla source copy."); } } array = CreateUpgradeVolumesFromVanillaSources(spawnedStand.transform); } for (int i = 0; i < array.Length; i++) { array[i].itemVolume = (itemVolume)6; array[i].itemSecretShopType = (itemSecretShopType)0; if ((Object)(object)((Component)array[i]).gameObject.GetComponent() == (Object)null) { ((Component)array[i]).gameObject.AddComponent(); } bool flag = i < num; ((Component)array[i]).gameObject.SetActive(flag); ((Behaviour)array[i]).enabled = flag; } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Configured upgrade ItemVolumes: active={Math.Min(num, array.Length)}, total={array.Length}."); } } private static ItemVolume[] GetStandItemVolumes(GameObject stand) { return (from v in stand.GetComponentsInChildren(true) where (Object)(object)v != (Object)null orderby ((Component)v).transform.localPosition.y descending, ((Component)v).transform.localPosition.x select v).ToArray(); } private static void DisableExistingUpgradeVolumeChildren(ItemVolume[] volumes) { foreach (ItemVolume val in volumes) { if (!((Object)(object)val == (Object)null)) { ((Behaviour)val).enabled = false; ((Component)val).gameObject.SetActive(false); } } } private static ItemVolume[] CreateUpgradeVolumesFromVanillaSources(Transform targetStand) { //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) UpgradeStand val = FindOriginalUpgradeStand(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"[UpgradeStandSpawner] Cannot copy upgrade ItemVolumes: vanilla UpgradeStand not found."); return (ItemVolume[])(object)new ItemVolume[0]; } List list = FindAllVanillaUpgradeVolumeSources(((Component)val).transform).ToList(); List list2 = (from s in list.Where(IsLikelyOriginalUpgradeSlot) orderby s.LocalPosition.y descending, s.LocalPosition.x select s).Take(14).ToList(); if (Plugin.DebugLogs.Value) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Vanilla upgrade slot scan: all={list.Count}, accepted={list2.Count}, original={GetTransformPath(((Component)val).transform)}."); } foreach (UpgradeVolumeSource item in list.OrderBy((UpgradeVolumeSource s) => s.Distance).Take(24)) { bool flag = IsLikelyOriginalUpgradeSlot(item); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Vanilla upgrade slot candidate: accepted={flag}, distance={item.Distance:F2}, local={item.LocalPosition}, path={item.Path}"); } } } if (list2.Count == 0) { Plugin.Log.LogWarning((object)"[UpgradeStandSpawner] Cannot copy upgrade ItemVolumes: no nearby vanilla upgrade ItemVolumes found."); return (ItemVolume[])(object)new ItemVolume[0]; } if (list2.Count < 14) { Plugin.Log.LogWarning((object)$"[UpgradeStandSpawner] Only {list2.Count}/14 vanilla upgrade ItemVolume(s) accepted. Passive stand may have fewer upgrade slots."); } List list3 = new List(); for (int i = 0; i < list2.Count; i++) { UpgradeVolumeSource upgradeVolumeSource = list2[i]; GameObject val2 = Object.Instantiate(((Component)upgradeVolumeSource.Volume).gameObject, targetStand, false); ((Object)val2).name = $"MoreStandsForShops Upgrade Slot {i + 1:00}"; val2.transform.localPosition = upgradeVolumeSource.LocalPosition; val2.transform.localRotation = upgradeVolumeSource.LocalRotation; val2.transform.localScale = upgradeVolumeSource.LocalScale; val2.SetActive(true); ItemVolume val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } val3.itemVolume = (itemVolume)6; val3.itemSecretShopType = (itemSecretShopType)0; ((Behaviour)val3).enabled = true; if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } list3.Add(val3); if (Plugin.DebugLogs.Value) { ManualLogSource log = Plugin.Log; object[] obj = new object[4] { i + 1, upgradeVolumeSource.Path, upgradeVolumeSource.LocalPosition, null }; Quaternion localRotation = upgradeVolumeSource.LocalRotation; obj[3] = ((Quaternion)(ref localRotation)).eulerAngles.y; log.LogInfo((object)string.Format("[UpgradeStandSpawner] Copied vanilla upgrade slot {0}: source={1}, local={2}, yaw={3:F1}", obj)); } } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Copied {list3.Count} vanilla upgrade ItemVolume(s) for passive stand."); } return (from v in list3 orderby ((Component)v).transform.localPosition.y descending, ((Component)v).transform.localPosition.x select v).ToArray(); } private static IEnumerable FindAllVanillaUpgradeVolumeSources(Transform originalStand) { return from v in ShopSceneCache.Current.ItemVolumes where (Object)(object)v != (Object)null where ((Component)v).gameObject.activeInHierarchy where (int)v.itemVolume == 6 where !IsInsideModOwnedObject(((Component)v).transform) select new UpgradeVolumeSource(v, originalStand); } private static bool IsLikelyOriginalUpgradeSlot(UpgradeVolumeSource source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) Vector3 localPosition = source.LocalPosition; if (source.Distance <= 2.5f && Mathf.Abs(localPosition.x) <= 1.6f && localPosition.y >= 0.4f && localPosition.y <= 2.5f && localPosition.z >= -1.2f) { return localPosition.z <= 1.4f; } return false; } private static bool IsInsideModOwnedObject(Transform transform) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase)) { return true; } if (((Object)val).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase)) { return true; } val = val.parent; } return false; } private static float[] EvenlySpaced(float min, float max, int count) { if (count <= 1) { return new float[1] { (min + max) * 0.5f }; } float[] array = new float[count]; for (int i = 0; i < count; i++) { array[i] = Mathf.Lerp(min, max, (float)i / (float)(count - 1)); } return array; } private static bool PreparePrefab() { UpgradeStand val = FindOriginalUpgradeStand(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"[UpgradeStandSpawner] No vanilla UpgradeStand found in scene."); return false; } _cachedPrefab = Object.Instantiate(((Component)val).gameObject); ((Object)_cachedPrefab).name = "MoreStandsForShops_UpgradeStand_Prefab"; _cachedPrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_cachedPrefab); UpgradeStand component = _cachedPrefab.GetComponent(); if ((Object)(object)component != (Object)null) { UpgradeStandRerollController upgradeStandRerollController = _cachedPrefab.GetComponent(); if ((Object)(object)upgradeStandRerollController == (Object)null) { upgradeStandRerollController = _cachedPrefab.AddComponent(); } upgradeStandRerollController.ConfigureFromVanilla(component); Object.Destroy((Object)(object)component); } PhotonView component2 = _cachedPrefab.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } _prefabPrepared = true; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[UpgradeStandSpawner] Upgrade stand prefab prepared."); } return true; } private static void DisableItemVolumes(GameObject stand) { ItemVolume[] componentsInChildren = stand.GetComponentsInChildren(true); foreach (ItemVolume val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { ((Behaviour)val).enabled = false; ((Component)val).gameObject.SetActive(false); } } } private static UpgradeStand FindOriginalUpgradeStand() { return ShopSceneCache.Current.Transforms.Select((Transform t) => (!((Object)(object)t == (Object)null)) ? ((Component)t).GetComponent() : null).FirstOrDefault((Func)((UpgradeStand s) => (Object)(object)s != (Object)null && ((Component)s).gameObject.activeInHierarchy && !((Object)s).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) && !((Object)s).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase))); } private static bool IsPaintingSecretShopPresent() { return ShopSceneCache.Current.Transforms.Any((Transform t) => (Object)(object)t != (Object)null && ((Component)t).gameObject.activeInHierarchy && ((Object)t).name == "Module - Shop - DE - Painting Secret Shop(Clone)"); } private static bool IsAgainstWall(Vector3 position, Quaternion rotation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) Vector3 val = rotation * Vector3.back; float num = 0.5f; int num2 = Physics.RaycastNonAlloc(position + Vector3.up * 0.5f, val, WallHits, num, -1, (QueryTriggerInteraction)1); for (int i = 0; i < num2; i++) { RaycastHit val2 = WallHits[i]; if (!((Object)(object)((RaycastHit)(ref val2)).transform == (Object)null) && Mathf.Abs(((RaycastHit)(ref val2)).normal.y) < 0.1f && IsStructuralShopSurface(GetTransformPath(((RaycastHit)(ref val2)).transform).ToLowerInvariant())) { return true; } } return false; } private static bool HasProtectedOverlap(Vector3 position, Quaternion rotation, bool protectPaintingObjects, out string objectName) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) objectName = null; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0.85f, 1.1f, 0.55f); Vector3 val2 = position + Vector3.up * val.y; Bounds val3 = BuildWorldBounds(val2, val, rotation, 0.03f); Collider[] array = Physics.OverlapBox(val2, val, rotation, -1, (QueryTriggerInteraction)1); foreach (Collider val4 in array) { if ((Object)(object)val4 == (Object)null || (Object)(object)((Component)val4).transform == (Object)null) { continue; } string text = GetTransformPath(((Component)val4).transform).ToLowerInvariant(); if (!((Object)((Component)val4).transform).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) && !((Object)((Component)val4).transform).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase)) { if (IsProtected(((Component)val4).transform, protectPaintingObjects)) { objectName = ((Object)((Component)val4).transform).name; return true; } if (!IsStructuralShopSurface(text) && !text.Contains("collider")) { text.Contains("trigger"); } } } Renderer[] renderers = ShopSceneCache.Current.Renderers; foreach (Renderer val5 in renderers) { if ((Object)(object)val5 == (Object)null || !((Component)val5).gameObject.activeInHierarchy) { continue; } Transform transform = ((Component)val5).transform; if (!((Object)transform).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) && !((Object)transform).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase) && IsProtected(transform, protectPaintingObjects)) { Bounds bounds = val5.bounds; if (((Bounds)(ref bounds)).Intersects(val3)) { objectName = GetTransformPath(transform); return true; } } } return false; } private static bool IsProtected(Transform t) { return IsProtected(t, IsPaintingSecretShopPresent()); } private static bool IsProtected(Transform t, bool protectPaintingObjects) { string text = GetTransformPath(t).ToLowerInvariant(); string[] array = new string[20] { "cash register", "cashier", "cashiers desk", "shop owner", "shopkeeper", "upgrade stand", "health stand", "revive stand", "battery upgrade stand", "item stands", "valuable shelf", "weapon stand", "weapon shelf", "extraction", "truck", "door", "secret", "hidden", "passage", "entrance" }; if (protectPaintingObjects && text.Contains("painting")) { return true; } string[] array2 = array; foreach (string value in array2) { if (text.Contains(value)) { return true; } } if ((Object)(object)((Component)t).GetComponentInChildren(true) != (Object)null) { return true; } if ((Object)(object)((Component)t).GetComponentInParent(true) != (Object)null) { return true; } return false; } private static bool IsStructuralShopSurface(string path) { string text = path; int num = text.LastIndexOf('/'); if (num >= 0 && num + 1 < text.Length) { text = text.Substring(num + 1); } if (!path.Contains("/walls/") && !path.Contains("/floor") && !path.Contains("/ceiling") && !path.Contains("wall window") && !path.Contains("window shop") && !path.Contains("window glass")) { switch (text) { default: if (!text.StartsWith("wall ") && !text.StartsWith("wall_") && !text.Contains("wall collider") && !text.Contains(" wall ")) { return text.Contains("wall"); } break; case "walls": case "floor": case "ceiling": break; } } return true; } private static bool IsShopModulePath(string path) { return path.Contains("level generator/level/module - shop"); } private static List DisableMovableOverlaps(Vector3 position, Quaternion rotation) { //IL_001c: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) bool protectPaintingObjects = IsPaintingSecretShopPresent(); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(1.15f, 1.15f, 0.75f); Vector3 val2 = position + Vector3.up * val.y; Bounds val3 = BuildWorldBounds(val2, val, rotation, 0.03f); HashSet disabledTargets = new HashSet(); List list = new List(); MoveCartOverlaps(position, rotation); Collider[] array = Physics.OverlapBox(val2, val, rotation, -1, (QueryTriggerInteraction)1); foreach (Collider val4 in array) { if (!((Object)(object)val4 == (Object)null) && !((Object)(object)((Component)val4).transform == (Object)null) && !((Object)((Component)val4).transform).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) && !((Object)((Component)val4).transform).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase)) { string path = GetTransformPath(((Component)val4).transform).ToLowerInvariant(); if (IsShopModulePath(path) && !IsProtected(((Component)val4).transform, protectPaintingObjects) && !IsStructuralShopSurface(path)) { TryDisableDecorativeTarget(FindDecorativeDisableRoot(((Component)val4).transform), disabledTargets, list, "collider", protectPaintingObjects); } } } Renderer[] renderers = ShopSceneCache.Current.Renderers; foreach (Renderer val5 in renderers) { if ((Object)(object)val5 == (Object)null || !((Component)val5).gameObject.activeInHierarchy) { continue; } Transform transform = ((Component)val5).transform; if (((Object)transform).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) || ((Object)transform).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase)) { continue; } Bounds bounds = val5.bounds; if (((Bounds)(ref bounds)).Intersects(val3)) { string text = GetTransformPath(transform).ToLowerInvariant(); if (IsShopModulePath(text) && !IsProtected(transform, protectPaintingObjects) && !IsStructuralShopSurface(text) && !text.Contains("collider") && !text.Contains("trigger")) { TryDisableDecorativeTarget(FindDecorativeDisableRoot(transform), disabledTargets, list, "renderer", protectPaintingObjects); } } } DisableMagazineDisplaysInsideStand(BuildMagazineCleanupBounds(val2, val, rotation), disabledTargets, list); return list; } private static int MoveCartOverlaps(Vector3 position, Quaternion rotation) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(1.2f, 1.15f, 0.85f); Vector3 val2 = position + Vector3.up * val.y; Bounds val3 = BuildWorldBounds(val2, val, rotation, 0.05f); Vector3 standForward = GetStandForward(rotation); HashSet hashSet = new HashSet(); Collider[] array = Physics.OverlapBox(val2, val, rotation, -1, (QueryTriggerInteraction)1); foreach (Collider val4 in array) { if (!((Object)(object)val4 == (Object)null) && !((Object)(object)((Component)val4).transform == (Object)null)) { Transform val5 = FindCartMoveRoot(((Component)val4).transform); if (!((Object)(object)val5 == (Object)null) && !hashSet.Contains(val5) && TryGetCombinedObjectBounds(val5, out var bounds) && ((Bounds)(ref bounds)).Intersects(val3)) { Vector3 moveOffset = CalculateCartMoveOffset(val3, bounds, standForward); MoveCartTarget(val5, moveOffset, hashSet); } } } return hashSet.Count; } private static Vector3 CalculateCartMoveOffset(Bounds standBounds, Bounds cartBounds, Vector3 moveDirection) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) float num = ProjectBoundsHalfExtent(standBounds, moveDirection); float num2 = ProjectBoundsHalfExtent(cartBounds, moveDirection); float num3 = Vector3.Dot(((Bounds)(ref cartBounds)).center - ((Bounds)(ref standBounds)).center, moveDirection); float num4 = num + num2 + 0.35f; float num5 = Mathf.Max(1f, num4 - num3); return moveDirection * num5; } private static float ProjectBoundsHalfExtent(Bounds bounds, Vector3 axis) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Abs(axis.x), Mathf.Abs(axis.y), Mathf.Abs(axis.z)); return Vector3.Dot(((Bounds)(ref bounds)).extents, val); } private static Vector3 GetStandForward(Quaternion rotation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(rotation * Vector3.forward, Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude > 0.001f)) { return Vector3.forward; } return ((Vector3)(ref val)).normalized; } private static Transform FindCartMoveRoot(Transform transform) { if ((Object)(object)transform == (Object)null) { return null; } ItemAttributes componentInParent = ((Component)transform).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && IsMovableCartItem(componentInParent.item)) { return ((Component)componentInParent).transform; } return FindNamedCartAncestor(transform); } private static Transform FindNamedCartAncestor(Transform transform) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (IsMovableCartName(((Object)val).name.ToLowerInvariant())) { return val; } val = val.parent; } return null; } private static bool IsMovableCartItem(Item item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 if ((Object)(object)item == (Object)null) { return false; } if ((int)item.itemType == 2 || (int)item.itemType == 12) { return true; } return IsMovableCartName(((Object)item).name.ToLowerInvariant()); } private static bool IsMovableCartName(string name) { if (!name.Contains("item cart medium") && !name.Contains("item cart small") && !name.Contains("item cart large") && !name.Contains("cart medium") && !name.Contains("cart small") && !name.Contains("c.a.r.t.") && !name.Contains("pocket c.a.r.t")) { return name.Contains("pocket cart"); } return true; } private static void MoveCartTarget(Transform moveTarget, Vector3 moveOffset, HashSet movedTargets) { //IL_002f: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)moveTarget == (Object)null) && !((Object)moveTarget).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) && !((Object)(object)((Component)moveTarget).GetComponentInParent(true) != (Object)null)) { Vector3 position = moveTarget.position; moveTarget.position = position + moveOffset; Rigidbody[] componentsInChildren = ((Component)moveTarget).GetComponentsInChildren(true); foreach (Rigidbody obj in componentsInChildren) { obj.velocity = Vector3.zero; obj.angularVelocity = Vector3.zero; obj.Sleep(); } Physics.SyncTransforms(); movedTargets.Add(moveTarget); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[UpgradeStandSpawner] Moved cart away from upgrade stand: {GetTransformPath(moveTarget)} {position} -> {moveTarget.position}"); } } } private static void DisableMagazineDisplaysInsideStand(Bounds standBounds, HashSet disabledTargets, List disabledPaths) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) Transform[] transforms = ShopSceneCache.Current.Transforms; foreach (Transform val in transforms) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && IsMagazineDisplayPath(GetTransformPath(val).ToLowerInvariant())) { Transform val2 = FindMagazineDisplayRoot(val); if (!((Object)(object)val2 == (Object)null) && !disabledTargets.Contains(val2) && TryGetCombinedObjectBounds(val2, out var bounds) && ((Bounds)(ref bounds)).Intersects(standBounds)) { TryDisableDecorativeTarget(val2, disabledTargets, disabledPaths, "magazine-display"); } } } } private static Bounds BuildMagazineCleanupBounds(Vector3 center, Vector3 halfExtents, Quaternion rotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Vector3 localHalfExtents = default(Vector3); ((Vector3)(ref localHalfExtents))..ctor(halfExtents.x + 1.1f, halfExtents.y + 0.35f, halfExtents.z + 0.55f); return BuildWorldBounds(center, localHalfExtents, rotation, 0.05f); } private static bool IsMagazineDisplayPath(string path) { if (!path.Contains("shop magazine holder") && !path.Contains("shop magazine stand")) { return path.Contains("magazines"); } return true; } private static Transform FindMagazineDisplayRoot(Transform transform) { Transform val = transform; while ((Object)(object)val != (Object)null) { string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("shop magazine holder") || text.Contains("shop magazine stand")) { return val; } val = val.parent; } return FindDecorativeDisableRoot(transform); } private static bool TryGetCombinedObjectBounds(Transform root, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0090: 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) //IL_0084: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } Collider[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && val2.enabled) { if (!flag) { bounds = val2.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2.bounds); } } } return flag; } private static bool TryDisableDecorativeTarget(Transform disableTarget, HashSet disabledTargets, List disabledPaths, string reason, bool protectPaintingObjects = false) { if ((Object)(object)disableTarget == (Object)null) { return false; } if (disabledTargets.Contains(disableTarget)) { return false; } if (((Object)disableTarget).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase)) { return false; } if (((Object)disableTarget).name.StartsWith("ExtraItemsShop", StringComparison.OrdinalIgnoreCase)) { return false; } if (IsUnsafeDisableRoot(disableTarget)) { return false; } string path = GetTransformPath(disableTarget).ToLowerInvariant(); bool flag = reason == "magazine-display" || IsMagazineDisplayPath(path); if (!IsShopModulePath(path)) { return false; } if (IsProtected(disableTarget, protectPaintingObjects)) { return false; } if (!flag && IsStructuralShopSurface(path)) { return false; } ((Component)disableTarget).gameObject.SetActive(false); disabledTargets.Add(disableTarget); disabledPaths.Add(GetTransformPath(disableTarget)); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[UpgradeStandSpawner] Disabled overlapping non-critical object via " + reason + ": " + GetTransformPath(disableTarget))); } return true; } private static bool IsUnsafeDisableRoot(Transform transform) { string text = ((Object)transform).name.ToLowerInvariant(); switch (text) { default: if (!text.Contains("---- level") && !text.StartsWith("module - shop") && !(text == "level")) { return text == "level generator"; } break; case "props": case "items": case "item stands": case "dependencies": case "walls": case "top": case "bot": case "left": case "right": case "connected": case "not connected": case "floor": case "ceiling": break; } return true; } private static Bounds BuildWorldBounds(Vector3 center, Vector3 localHalfExtents, Quaternion rotation, float padding) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) Vector3 val = rotation * Vector3.right; Vector3 val2 = rotation * Vector3.up; Vector3 val3 = rotation * Vector3.forward; Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(Mathf.Abs(val.x) * localHalfExtents.x + Mathf.Abs(val2.x) * localHalfExtents.y + Mathf.Abs(val3.x) * localHalfExtents.z, Mathf.Abs(val.y) * localHalfExtents.x + Mathf.Abs(val2.y) * localHalfExtents.y + Mathf.Abs(val3.y) * localHalfExtents.z, Mathf.Abs(val.z) * localHalfExtents.x + Mathf.Abs(val2.z) * localHalfExtents.y + Mathf.Abs(val3.z) * localHalfExtents.z); val4 += Vector3.one * padding; return new Bounds(center, val4 * 2f); } private static Transform FindDecorativeDisableRoot(Transform transform) { for (Transform val = transform; (Object)(object)val != (Object)null && (Object)(object)val.parent != (Object)null; val = val.parent) { string text = ((Object)val.parent).name.ToLowerInvariant(); switch (text) { default: if (!text.Contains("---- level") && !text.StartsWith("module - shop")) { continue; } break; case "props": case "items": case "item stands": case "dependencies": case "not connected": case "connected": case "walls": break; } return val; } return transform; } private static Transform FindTransformByPath(string path) { return ScenePathUtility.FindTransformByPath(path); } private static string GetTransformPath(Transform t) { return ShopSceneCache.Current.GetTransformPath(t); } } } namespace MoreStandsForShops.Shop { internal static class MultiSizeSlotController { private static readonly HashSet HandledGroups = new HashSet(); internal static void ResetForShop() { HandledGroups.Clear(); } internal static bool TrySkipHandledSlot(ItemVolume itemVolume, out bool result) { result = false; MoreStandsMultiSizeVolume moreStandsMultiSizeVolume = (((Object)(object)itemVolume == (Object)null) ? null : ((Component)itemVolume).GetComponent()); if ((Object)(object)moreStandsMultiSizeVolume == (Object)null || string.IsNullOrEmpty(moreStandsMultiSizeVolume.GroupId)) { return false; } if (HandledGroups.Contains(moreStandsMultiSizeVolume.GroupId)) { result = false; return true; } return false; } internal static void NoteSpawnResult(ItemVolume itemVolume, bool spawned) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (!spawned) { return; } MoreStandsMultiSizeVolume moreStandsMultiSizeVolume = (((Object)(object)itemVolume == (Object)null) ? null : ((Component)itemVolume).GetComponent()); if (!((Object)(object)moreStandsMultiSizeVolume == (Object)null) && !string.IsNullOrEmpty(moreStandsMultiSizeVolume.GroupId)) { HandledGroups.Add(moreStandsMultiSizeVolume.GroupId); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[MultiSizeSlot] Group {moreStandsMultiSizeVolume.GroupId} handled by {itemVolume.itemVolume}."); } } } } internal static class ShelfItemSelector { private static readonly Dictionary SpawnedByZone = new Dictionary(); private static readonly Dictionary SpawnedByItem = new Dictionary(); internal static void Reset() { SpawnedByZone.Clear(); SpawnedByItem.Clear(); } internal static Item Select(MoreStandsShelfZone zone, itemVolume slotVolume) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StatsManager.instance == (Object)null || SpawnedCount(zone) >= TargetFor(zone)) { return null; } return (from item in StatsManager.instance.itemDictionary.Values where (Object)(object)item != (Object)null && !item.disabled where IsZoneItem(item, zone) where !IsBlockedShelfItem(item, zone) where item.itemVolume == slotVolume where Plugin.GetItemSpawnChance(item) > 0 where SameItemCount(zone, item) < SameCopyLimit(zone) select item).OrderBy(WeightedRandomSortKey).FirstOrDefault(); } internal static void RecordSpawn(MoreStandsShelfZone zone, Item item) { SpawnedByZone[zone] = SpawnedCount(zone) + 1; string key = ItemKey(zone, item); SpawnedByItem[key] = ((!SpawnedByItem.TryGetValue(key, out var value)) ? 1 : (value + 1)); } internal static int TargetFor(MoreStandsShelfZone zone) { string key = zone switch { MoreStandsShelfZone.Drone => "Drones", MoreStandsShelfZone.Crystal => "Power Crystals", MoreStandsShelfZone.Grenade => "Grenades", _ => string.Empty, }; if (!Plugin.ItemCounts.TryGetValue(key, out var value)) { return 0; } return value.Value; } internal static int SpawnedCount(MoreStandsShelfZone zone) { if (!SpawnedByZone.TryGetValue(zone, out var value)) { return 0; } return value; } internal static string ItemName(Item item) { if ((Object)(object)item == (Object)null) { return ""; } if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } private static double WeightedRandomSortKey(Item item) { int num = Math.Max(1, Plugin.GetItemSpawnChance(item)); return (0.0 - Math.Log(Math.Max(Random.value, 1E-06f))) / (double)num; } private static bool IsZoneItem(Item item, MoreStandsShelfZone zone) { ShopStockCategory category = ShopStockCatalog.GetCategory(item); return zone switch { MoreStandsShelfZone.Drone => category == ShopStockCategory.Drones, MoreStandsShelfZone.Crystal => category == ShopStockCategory.PowerCrystals, MoreStandsShelfZone.Grenade => category == ShopStockCategory.Grenades, _ => false, }; } private static bool IsBlockedShelfItem(Item item, MoreStandsShelfZone zone) { if (zone != MoreStandsShelfZone.Grenade) { return false; } if (!IsDuctTapedGrenade(((Object)item).name)) { return IsDuctTapedGrenade(ItemName(item)); } return true; } private static bool IsDuctTapedGrenade(string name) { if (string.IsNullOrWhiteSpace(name)) { return false; } string text = name.ToLowerInvariant(); if (text.Contains("duct") && text.Contains("tape")) { return text.Contains("grenade"); } return false; } private static int SameCopyLimit(MoreStandsShelfZone zone) { string text; switch (zone) { case MoreStandsShelfZone.Crystal: return TargetFor(zone); case MoreStandsShelfZone.Drone: text = "Drones"; break; case MoreStandsShelfZone.Grenade: text = "Grenades"; break; default: text = string.Empty; break; } string key = text; if (!Plugin.SameItemCopies.TryGetValue(key, out var value)) { return TargetFor(zone); } return value.Value; } private static int SameItemCount(MoreStandsShelfZone zone, Item item) { if (!SpawnedByItem.TryGetValue(ItemKey(zone, item), out var value)) { return 0; } return value; } private static string ItemKey(MoreStandsShelfZone zone, Item item) { return zone.ToString() + ":" + ItemName(item); } } internal static class ShelfSpawnController { internal static void ResetForShop() { ShelfItemSelector.Reset(); } internal static void PrepareVolumesForPopulate(PunManager punManager) { if (ShopManager.instance?.itemVolumes == null) { return; } foreach (ItemVolume item in ShopManager.instance.itemVolumes.Where((ItemVolume volume) => (Object)(object)volume != (Object)null)) { MoreStandsShelfVolume component = ((Component)item).GetComponent(); if ((Object)(object)component != (Object)null) { component.Handled = false; } } SpawnAndRemoveShelfVolumes(punManager); ShopManager.instance.itemVolumes = (from volume in ShopManager.instance.itemVolumes where (Object)(object)volume != (Object)null orderby ((Object)(object)((Component)volume).GetComponent() == (Object)null) ? 1 : 0 select volume).ToList(); int num = ShopManager.instance.itemVolumes.Count((ItemVolume volume) => (Object)(object)((Component)volume).GetComponent() != (Object)null); if (num > 0 && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfSpawnController] Prioritized {num} additional upgrade ItemVolume(s)."); } } private static void SpawnAndRemoveShelfVolumes(PunManager punManager) { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) List list = (from volume in ShopManager.instance.itemVolumes where (Object)(object)volume != (Object)null && (Object)(object)((Component)volume).GetComponent() != (Object)null orderby (((Component)volume).GetComponent().Zone != MoreStandsShelfZone.Crystal) ? 1 : 0, ((Component)volume).transform.position.y descending, ((Component)volume).transform.position.x select volume).ToList(); if (list.Count == 0) { return; } ShopManager.instance.itemVolumes.RemoveAll((ItemVolume volume) => (Object)(object)volume == (Object)null || (Object)(object)((Component)volume).GetComponent() != (Object)null); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfSpawnController] Removed {list.Count} controlled shelf ItemVolume(s) from vanilla population."); } foreach (ItemVolume item in list) { MoreStandsShelfVolume component = ((Component)item).GetComponent(); if ((Object)(object)component == (Object)null) { continue; } component.Handled = true; Item val = ShelfItemSelector.Select(component.Zone, item.itemVolume); if ((Object)(object)val == (Object)null) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfSpawnController] Shelf slot skipped: zone={component.Zone}, slotVolume={item.itemVolume}, target={ShelfItemSelector.TargetFor(component.Zone)}, spawned={ShelfItemSelector.SpawnedCount(component.Zone)}."); } } else if (!VanillaShopItemSpawner.TrySpawnSingle(punManager, item, val, isSecret: false)) { Plugin.Log.LogWarning((object)$"[ShelfSpawnController] Vanilla rejected shelf item: zone={component.Zone}, item={ShelfItemSelector.ItemName(val)}, itemVolume={val.itemVolume}, slotVolume={item.itemVolume}."); } else { ShelfItemSelector.RecordSpawn(component.Zone, val); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfSpawnController] Spawned shelf item: zone={component.Zone}, item={ShelfItemSelector.ItemName(val)}, slotVolume={item.itemVolume}."); } } } } internal static bool TryHandleSpawnShopItem(PunManager punManager, ItemVolume itemVolume, List itemList, ref int spawnCount, bool isSecret, out bool result) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) result = false; MoreStandsShelfVolume moreStandsShelfVolume = (((Object)(object)itemVolume == (Object)null) ? null : ((Component)itemVolume).GetComponent()); if ((Object)(object)moreStandsShelfVolume == (Object)null) { return false; } if (!Plugin.EnableMod.Value || isSecret || !SemiFunc.IsMasterClientOrSingleplayer()) { result = false; return true; } if (moreStandsShelfVolume.Handled) { result = false; return true; } if (!IsAllowedVanillaList(moreStandsShelfVolume.Zone, itemList)) { result = false; return true; } moreStandsShelfVolume.Handled = true; Item val = ShelfItemSelector.Select(moreStandsShelfVolume.Zone, itemVolume.itemVolume); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)$"[ShelfSpawnController] No valid {moreStandsShelfVolume.Zone} item for slotVolume={itemVolume.itemVolume}; slot skipped."); result = false; return true; } bool flag = VanillaShopItemSpawner.TrySpawnSingle(punManager, itemVolume, val, isSecret); if (flag) { ShelfItemSelector.RecordSpawn(moreStandsShelfVolume.Zone, val); if (!isSecret) { spawnCount++; } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfSpawnController] Spawned {moreStandsShelfVolume.Zone}: {ShelfItemSelector.ItemName(val)} in slotVolume={itemVolume.itemVolume}."); } } else { Plugin.Log.LogWarning((object)$"[ShelfSpawnController] Vanilla rejected {moreStandsShelfVolume.Zone}: {ShelfItemSelector.ItemName(val)} itemVolume={val.itemVolume}, slotVolume={itemVolume.itemVolume}."); } result = flag; return true; } private static bool IsAllowedVanillaList(MoreStandsShelfZone zone, List itemList) { if ((Object)(object)ShopManager.instance == (Object)null) { return false; } return zone switch { MoreStandsShelfZone.Drone => itemList == ShopManager.instance.potentialItems, MoreStandsShelfZone.Crystal => itemList == ShopManager.instance.potentialItemConsumables, MoreStandsShelfZone.Grenade => itemList == ShopManager.instance.potentialItems, _ => false, }; } } internal static class ShopBudgetPlanner { internal static void ApplyConfiguredBudgets(ShopManager shopManager) { if (!((Object)(object)shopManager == (Object)null)) { int itemSpawnTargetAmount = ((IEnumerable)ShopStockCatalog.StandardBudgetCountKeys).Sum((Func)GetCount); shopManager.itemSpawnTargetAmount = itemSpawnTargetAmount; shopManager.itemConsumablesAmount = 0; shopManager.itemUpgradesAmount = GetCount("Total Upgrades"); shopManager.itemHealthPacksAmount = GetCount("Health Packs"); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)string.Format("[ShopBudgetPlanner] Shop budgets set: standard={0}, vanillaCrystals={1}, customDrones={2}, customCrystals={3}, upgrades={4}, health={5}.", shopManager.itemSpawnTargetAmount, shopManager.itemConsumablesAmount, GetCount("Drones"), GetCount("Power Crystals"), shopManager.itemUpgradesAmount, shopManager.itemHealthPacksAmount)); } } } internal static void ApplyFillAllShopSlotBudget(ShopManager shopManager) { if (!((Object)(object)shopManager == (Object)null) && Plugin.EnableMod.Value && Plugin.DisableShopPoolLimit.Value) { int num = shopManager.potentialItems?.Count ?? 0; int num2 = shopManager.itemVolumes?.Count ?? 0; int itemSpawnTargetAmount = shopManager.itemSpawnTargetAmount; shopManager.itemSpawnTargetAmount = Math.Max(itemSpawnTargetAmount, Math.Max(num, num2)); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopBudgetPlanner] Shop pool limit disabled: standard target {itemSpawnTargetAmount}->{shopManager.itemSpawnTargetAmount}, standardPool={num}, activeVolumes={num2}."); } } } private static int GetCount(string key) { if (!Plugin.ItemCounts.TryGetValue(key, out var value)) { return 0; } return value.Value; } } internal static class ShopItemLimitPlanner { private static bool _spawnChanceConfigsEnsured; internal static void ResetForSession() { _spawnChanceConfigsEnsured = false; } internal static void ApplyConfiguredItemLimits() { Dictionary dictionary = StatsManager.instance?.itemDictionary; if (dictionary == null) { return; } if (!_spawnChanceConfigsEnsured) { Plugin.EnsureItemSpawnChanceConfigs(dictionary.Values); _spawnChanceConfigsEnsured = true; } foreach (Item value2 in dictionary.Values) { if (!((Object)(object)value2 == (Object)null) && ShopStockCatalog.TryGetConfigKeys(value2, out var countKey, out var _) && Plugin.ItemCounts.TryGetValue(countKey, out var value)) { int num = (value2.maxAmount = (value2.maxAmountInShop = value.Value)); value2.maxPurchase = num > 0; value2.maxPurchaseAmount = num; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopItemLimitPlanner] Set {value2.itemName} maxAmountInShop to {num}"); } } } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[ShopItemLimitPlanner] Applied item count overrides."); } } } internal static class ShopPoolPlanner { internal static void PreparePools(ShopManager shopManager) { if (!((Object)(object)shopManager == (Object)null)) { TopUpPotentialPoolsFromStats(shopManager); RemoveControlledShelfItemsFromVanillaPools(shopManager); shopManager.potentialItemUpgrades = FilterListByConfiguredLimits(shopManager.potentialItemUpgrades, "upgrades"); shopManager.potentialItems = FilterListByConfiguredLimits(shopManager.potentialItems, "standard"); shopManager.potentialItemConsumables = FilterListByConfiguredLimits(shopManager.potentialItemConsumables, "consumables"); shopManager.potentialItemHealthPacks = FilterListByConfiguredLimits(shopManager.potentialItemHealthPacks, "health"); } } private static void RemoveControlledShelfItemsFromVanillaPools(ShopManager shopManager) { if (!((Object)(object)shopManager == (Object)null)) { int num = 0; num += RemoveControlledShelfItems(shopManager.potentialItems); num += RemoveControlledShelfItems(shopManager.potentialItemConsumables); num += RemoveControlledShelfItems(shopManager.potentialItemUpgrades); num += RemoveControlledShelfItems(shopManager.potentialItemHealthPacks); if (num > 0 && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopPoolPlanner] Removed {num} controlled shelf entries from vanilla pools; custom shelf handling owns them."); } } } private static int RemoveControlledShelfItems(List items) { if (items == null) { return 0; } int count = items.Count; items.RemoveAll((Item item) => (Object)(object)item != (Object)null && ((int)item.itemType == 0 || (int)item.itemType == 5 || (int)item.itemType == 6)); return count - items.Count; } private static int GetCount(string key) { if (!Plugin.ItemCounts.TryGetValue(key, out var value)) { return 0; } return value.Value; } private static void TopUpPotentialPoolsFromStats(ShopManager shopManager) { Dictionary dictionary = StatsManager.instance?.itemDictionary; if ((Object)(object)shopManager == (Object)null || dictionary == null) { return; } string countKey; string copyKey; foreach (var item in from item in dictionary.Values where (Object)(object)item != (Object)null && !item.disabled select new { Item = item, HasKeys = ShopStockCatalog.TryGetConfigKeys(item, out countKey, out copyKey), CountKey = countKey } into entry where entry.HasKeys && !IsCustomShelfOnlyCountKey(entry.CountKey) && GetCount(entry.CountKey) > 0 group entry by entry.CountKey) { string key = item.Key; int count = GetCount(key); if (count <= 0) { continue; } List poolForItem = GetPoolForItem(shopManager, item.First().Item); if (poolForItem == null) { continue; } int num = CountPoolCategory(poolForItem, key); int num2 = count - num; if (num2 > 0) { List candidates = item.Select(entry => entry.Item).OrderBy(WeightedRandomSortKey).ToList(); int num3 = AddCategoryCandidates(poolForItem, candidates, key, num2); if (Plugin.DebugLogs.Value && num3 > 0 && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopPoolPlanner] Topped up {key} pool: added={num3}, before={num}, target={count}."); } } } } private static bool IsCustomShelfOnlyCountKey(string countKey) { if (!(countKey == "Drones") && !(countKey == "Power Crystals")) { return countKey == "Grenades"; } return true; } private static int AddCategoryCandidates(List pool, List candidates, string countKey, int missing) { int num = 0; int num2 = candidates.Count * 8; int num3 = 0; while (num < missing && candidates.Count > 0 && num3 < num2) { Item item = candidates[num3 % candidates.Count]; if (CanAddCandidate(pool, item, countKey)) { pool.Add(item); num++; } num3++; } return num; } private static bool CanAddCandidate(List pool, Item item, string countKey) { if ((Object)(object)item == (Object)null || item.disabled) { return false; } if (!ShopStockCatalog.TryGetConfigKeys(item, out var countKey2, out var copyKey)) { return false; } if (countKey2 != countKey) { return false; } int num = SemiFunc.StatGetItemsPurchased(((Object)item).name); int num2 = pool.Count((Item existing) => (Object)(object)existing != (Object)null && ((Object)existing).name == ((Object)item).name); if (num2 + num >= item.maxAmountInShop) { return false; } if (copyKey != null && Plugin.SameItemCopies.TryGetValue(copyKey, out var value) && num2 >= value.Value) { return false; } return true; } private static int CountPoolCategory(List pool, string countKey) { string countKey2; string copyKey; return pool.Count((Item item) => (Object)(object)item != (Object)null && ShopStockCatalog.TryGetConfigKeys(item, out countKey2, out copyKey) && countKey2 == countKey); } private static List GetPoolForItem(ShopManager shopManager, Item item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) itemType itemType = item.itemType; if ((int)itemType != 3) { if ((int)itemType != 5) { if ((int)itemType == 8) { return shopManager.potentialItemHealthPacks; } if ((int)item.itemSecretShopType == 0) { return shopManager.potentialItems; } return null; } return shopManager.potentialItemConsumables; } return shopManager.potentialItemUpgrades; } private static List FilterListByConfiguredLimits(List items, string listName) { if (items == null || items.Count == 0) { return items; } int count = items.Count; List list = ApplyItemSpawnChanceOrder(items, listName); Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(); List list2 = new List(list.Count); foreach (Item item in list) { if ((Object)(object)item == (Object)null) { continue; } if (!ShopStockCatalog.TryGetConfigKeys(item, out var countKey, out var copyKey)) { list2.Add(item); continue; } int count2 = GetCount(countKey); int value; int num = (dictionary.TryGetValue(countKey, out value) ? value : 0); if (count2 <= 0 || num >= count2) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopPoolPlanner] Filtered out {ItemName(item)}: category {countKey} limit {count2} reached."); } continue; } if (copyKey != null && Plugin.SameItemCopies.TryGetValue(copyKey, out var value2)) { string name = ((Object)item).name; int value3; int num2 = (dictionary2.TryGetValue(name, out value3) ? value3 : 0); if (num2 >= value2.Value) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopPoolPlanner] Filtered out excess copy of {ItemName(item)} (limit {value2.Value})."); } continue; } dictionary2[name] = num2 + 1; } dictionary[countKey] = num + 1; list2.Add(item); } if (Plugin.DebugLogs.Value) { string text = string.Join(", ", from kvp in dictionary orderby kvp.Key select $"{kvp.Key}={kvp.Value}/{GetCount(kvp.Key)}"); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopPoolPlanner] Filtered {listName} pool: {count} -> {list2.Count}. Category counts: {text}"); } } return list2; } private static List ApplyItemSpawnChanceOrder(List items, string listName) { List list = new List(items.Count); int num = 0; foreach (Item item in items) { if ((Object)(object)item == (Object)null) { continue; } if (item.disabled) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[ShopPoolPlanner] Filtered out " + ItemName(item) + " from " + listName + ": item is disabled.")); } } else if (Plugin.GetItemSpawnChance(item) <= 0) { num++; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[ShopPoolPlanner] Filtered out " + ItemName(item) + " from " + listName + ": item spawn chance is 0.")); } } else { list.Add(item); } } if (num > 0 && Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShopPoolPlanner] Removed {num} {listName} pool entries because item spawn chance is 0."); } return list.OrderBy(WeightedRandomSortKey).ToList(); } private static double WeightedRandomSortKey(Item item) { int num = Math.Max(1, Plugin.GetItemSpawnChance(item)); return (0.0 - Math.Log(Math.Max(Random.value, 1E-06f))) / (double)num; } private static string ItemName(Item item) { if ((Object)(object)item == (Object)null) { return ""; } if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } } internal static class ShopStockCatalog { private static readonly Dictionary ExactItemConfigKeys = new Dictionary { { "C.A.R.T. Cannon", ("C.A.R.T. Weapons", "C.A.R.T. Weapons") }, { "C.A.R.T. Laser", ("C.A.R.T. Weapons", "C.A.R.T. Weapons") } }; internal static IReadOnlyList StandardBudgetCountKeys { get; } = new string[11] { "Orbs", "Grenades", "Mines", "Melee", "Guns", "C.A.R.T. Weapons", "Launchers", "Tools", "Carts", "Pocket Carts", "Vehicles" }; internal static ShopStockCategory GetCategory(Item item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected I4, but got Unknown if ((Object)(object)item == (Object)null) { return ShopStockCategory.None; } itemType itemType = item.itemType; return (int)itemType switch { 3 => ShopStockCategory.Upgrades, 0 => ShopStockCategory.Drones, 5 => ShopStockCategory.PowerCrystals, 1 => ShopStockCategory.Orbs, 6 => ShopStockCategory.Grenades, 11 => ShopStockCategory.Mines, 7 => ShopStockCategory.Melee, 9 => ShopStockCategory.Guns, 15 => ShopStockCategory.Launchers, 13 => ShopStockCategory.Tools, 10 => ShopStockCategory.Tools, 8 => ShopStockCategory.HealthPacks, 2 => ShopStockCategory.Carts, 12 => ShopStockCategory.PocketCarts, 14 => ShopStockCategory.Vehicles, 4 => ShopStockCategory.None, _ => ShopStockCategory.None, }; } internal static bool TryGetConfigKeys(Item item, out string countKey, out string copyKey) { if (TryGetExactItemConfigKeys(item, out countKey, out copyKey)) { return true; } return TryGetConfigKeys(GetCategory(item), out countKey, out copyKey); } private static bool TryGetExactItemConfigKeys(Item item, out string countKey, out string copyKey) { countKey = null; copyKey = null; if ((Object)(object)item == (Object)null) { return false; } if (!TryGetExactItemConfigKeys(item.itemName, out countKey, out copyKey)) { return TryGetExactItemConfigKeys(((Object)item).name, out countKey, out copyKey); } return true; } private static bool TryGetExactItemConfigKeys(string itemName, out string countKey, out string copyKey) { countKey = null; copyKey = null; if (string.IsNullOrWhiteSpace(itemName) || !ExactItemConfigKeys.TryGetValue(itemName, out (string, string) value)) { return false; } (countKey, copyKey) = value; return true; } internal static bool TryGetConfigKeys(ShopStockCategory category, out string countKey, out string copyKey) { countKey = null; copyKey = null; switch (category) { case ShopStockCategory.Upgrades: countKey = "Total Upgrades"; copyKey = "Upgrades"; return true; case ShopStockCategory.Drones: countKey = "Drones"; copyKey = "Drones"; return true; case ShopStockCategory.PowerCrystals: countKey = "Power Crystals"; return true; case ShopStockCategory.Orbs: countKey = "Orbs"; return true; case ShopStockCategory.Grenades: countKey = "Grenades"; copyKey = "Grenades"; return true; case ShopStockCategory.Mines: countKey = "Mines"; copyKey = "Mines"; return true; case ShopStockCategory.Melee: countKey = "Melee"; copyKey = "Melee"; return true; case ShopStockCategory.Guns: countKey = "Guns"; copyKey = "Guns"; return true; case ShopStockCategory.Launchers: countKey = "Launchers"; copyKey = "Launchers"; return true; case ShopStockCategory.Tools: countKey = "Tools"; return true; case ShopStockCategory.HealthPacks: countKey = "Health Packs"; copyKey = "Health Packs"; return true; case ShopStockCategory.Carts: countKey = "Carts"; return true; case ShopStockCategory.PocketCarts: countKey = "Pocket Carts"; return true; case ShopStockCategory.Vehicles: countKey = "Vehicles"; return true; default: return false; } } } internal enum ShopStockCategory { None, Upgrades, Drones, PowerCrystals, Orbs, Grenades, Mines, Melee, Guns, Launchers, Tools, HealthPacks, Carts, PocketCarts, Vehicles } internal static class VanillaShopItemSpawner { private static readonly MethodInfo SpawnShopItemMethod = typeof(PunManager).GetMethod("SpawnShopItem", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[4] { typeof(ItemVolume), typeof(List), typeof(int).MakeByRefType(), typeof(bool) }, null); internal static bool IsCallingVanilla { get; private set; } internal static bool TrySpawnSingle(PunManager punManager, ItemVolume itemVolume, Item item, bool isSecret) { if ((Object)(object)punManager == (Object)null || (Object)(object)itemVolume == (Object)null || (Object)(object)item == (Object)null || SpawnShopItemMethod == null) { return false; } List list = new List { item }; int num = 0; object[] parameters = new object[4] { itemVolume, list, num, isSecret }; try { IsCallingVanilla = true; return (bool)SpawnShopItemMethod.Invoke(punManager, parameters); } catch (Exception arg) { Plugin.Log.LogError((object)$"[VanillaShopItemSpawner] Failed to call vanilla SpawnShopItem for {ItemName(item)}: {arg}"); return false; } finally { IsCallingVanilla = false; } } private static string ItemName(Item item) { if ((Object)(object)item == (Object)null) { return ""; } if (string.IsNullOrWhiteSpace(item.itemName)) { return ((Object)item).name; } return item.itemName; } } } namespace MoreStandsForShops.Rewriters { internal static class VanillaShelfTableRewriter { private sealed class TableLogicalSlot { internal readonly List Volumes = new List(); internal List AllTableVolumes { get; private set; } internal Vector2 Center { get; private set; } internal void Add(ItemVolume volume, Vector2 point) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Center = ((Volumes.Count == 0) ? point : ((Center * (float)Volumes.Count + point) / (float)(Volumes.Count + 1))); Volumes.Add(volume); if (AllTableVolumes == null) { List list2 = (AllTableVolumes = (from itemVolume in ((Component)((Component)volume).transform.parent).GetComponentsInChildren(true) where (Object)(object)itemVolume != (Object)null && IsTableVolumeType(itemVolume.itemVolume) where !((Object)itemVolume).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) where (Object)(object)((Component)itemVolume).GetComponent() == (Object)null select new TableVolumeTemplate(itemVolume)).ToList()); } } } private sealed class TableVolumeTemplate { internal readonly ItemVolume Source; internal readonly itemVolume ItemVolume; internal readonly string Name; internal readonly Vector3 LocalPosition; internal readonly Quaternion LocalRotation; internal readonly Vector3 LocalScale; internal readonly List Volumes; internal TableVolumeTemplate(ItemVolume source) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Source = source; ItemVolume = source.itemVolume; Name = ((Object)source).name; LocalPosition = ((Component)source).transform.localPosition; LocalRotation = ((Component)source).transform.localRotation; LocalScale = ((Component)source).transform.localScale; Volumes = new List(source.volumes); } } private readonly struct TableVolumePose { internal readonly TableVolumeTemplate Source; internal readonly Vector3 LocalPosition; internal readonly Quaternion LocalRotation; internal readonly Vector3 LocalScale; internal TableVolumePose(TableVolumeTemplate source, Vector3 localPosition, Quaternion localRotation, Vector3 localScale) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Source = source; LocalPosition = localPosition; LocalRotation = localRotation; LocalScale = localScale; } } private const string GeneratedPrefix = "MoreStandsForShops Vanilla Shelf Slot"; private const string MultiSizePrefix = "MoreStandsForShops Table Multi Slot"; private const float SameTableSlotDistance = 0.03f; private static readonly itemVolume[] TableSlotTypes; private static readonly Vector3[] HealthSlotPositions; private static readonly Vector3[] LowerSmallSlotPositions; internal static void Apply() { if (!Plugin.EnableVanillaShelfTableRewrite.Value) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)"[ShelfTableRewrite] Disabled in config."); } return; } List list = FindItemStandRoots("valuable shelf short (1)").ToList(); int num = 0; foreach (Transform item in list) { if (RewriteHealthShelf(item)) { num++; } } int num2 = ConvertVanillaTableVolumesInItemAreas(); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfTableRewrite] Rewritten health shelves={num}, converted table slot group(s)={num2}."); } } private static bool RewriteHealthShelf(Transform shelf) { //IL_0096: 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) if ((Object)(object)shelf == (Object)null || !((Component)shelf).gameObject.activeInHierarchy) { return false; } DisableOriginalShelfVolumes(shelf); if (((Component)shelf).GetComponentsInChildren(true).Any((ItemVolume volume) => (Object)(object)volume != (Object)null && ((Object)volume).name.StartsWith("MoreStandsForShops Vanilla Shelf Slot", StringComparison.OrdinalIgnoreCase))) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[ShelfTableRewrite] Shelf already has generated slots: " + GetTransformPath(shelf))); } return true; } for (int i = 0; i < HealthSlotPositions.Length; i++) { CreateVolumeSlot(shelf, string.Format("{0} Health {1:00}", "MoreStandsForShops Vanilla Shelf Slot", i + 1), (itemVolume)7, HealthSlotPositions[i]); } for (int j = 0; j < LowerSmallSlotPositions.Length; j++) { CreateVolumeSlot(shelf, string.Format("{0} Grenade {1:00}", "MoreStandsForShops Vanilla Shelf Slot", j + 1), (itemVolume)0, LowerSmallSlotPositions[j], MoreStandsShelfZone.Grenade); } if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ShelfTableRewrite] Created {HealthSlotPositions.Length} healthPack upper slot(s) and {LowerSmallSlotPositions.Length} grenade lower slot(s) on {GetTransformPath(shelf)}."); } return true; } private static void DisableOriginalShelfVolumes(Transform shelf) { ItemVolume[] componentsInChildren = ((Component)shelf).GetComponentsInChildren(true); foreach (ItemVolume val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)val).name.StartsWith("MoreStandsForShops Vanilla Shelf Slot", StringComparison.OrdinalIgnoreCase)) { ((Component)val).gameObject.SetActive(false); ((Behaviour)val).enabled = false; } } } private static int ConvertVanillaTableVolumesInItemAreas() { int num = 0; foreach (IGrouping item in (from volume in FindActiveVanillaTableVolumes() group volume by ((Component)volume).transform.parent into @group where (Object)(object)@group.Key != (Object)null select @group).ToList()) { Transform key = item.Key; if (((Component)key).GetComponentsInChildren(true).Any()) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[ShelfTableRewrite] Table already has multi-size slots: " + GetTransformPath(key))); } continue; } List list = (from volume in item orderby ((Component)volume).transform.localPosition.z, ((Component)volume).transform.localPosition.x, (int)volume.itemVolume select volume).ToList(); List list2 = BuildLogicalSlots(list); int created = 0; int reused = 0; int disabled = 0; for (int i = 0; i < list2.Count; i++) { TableLogicalSlot slot = list2[i]; string groupId = $"table-slot:{((Object)key).GetInstanceID()}:{i:00}"; RewriteLogicalTableSlot(key, slot, groupId, ref reused, ref created, ref disabled); } num += list2.Count; if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[ShelfTableRewrite] Converted table item area to multi-size slots: " + $"root={GetTransformPath(key)}, originalVolumes={list.Count}, " + $"slotGroups={list2.Count}, reused={reused}, created={created}, disabled={disabled}.")); } } return num; } private static void MarkMultiSizeVolume(ItemVolume volume, string groupId, itemVolume itemVolume) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) volume.itemVolume = itemVolume; volume.itemSecretShopType = (itemSecretShopType)0; ((Behaviour)volume).enabled = true; ((Component)volume).gameObject.SetActive(true); MoreStandsMultiSizeVolume moreStandsMultiSizeVolume = ((Component)volume).GetComponent(); if ((Object)(object)moreStandsMultiSizeVolume == (Object)null) { moreStandsMultiSizeVolume = ((Component)volume).gameObject.AddComponent(); } moreStandsMultiSizeVolume.GroupId = groupId; } private static ItemVolume CreateMultiSizeVolume(Transform parent, TableVolumePose pose, string groupId, itemVolume itemVolume) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(string.Format("{0} {1}", "MoreStandsForShops Table Multi Slot", itemVolume)); val.transform.SetParent(parent, false); ApplyPose(val.transform, pose); ItemVolume obj = val.AddComponent(); obj.itemVolume = itemVolume; obj.itemSecretShopType = (itemSecretShopType)0; obj.volumes = new List(pose.Source.Volumes); val.AddComponent().GroupId = groupId; return obj; } private static IEnumerable FindActiveVanillaTableVolumes() { return from volume in ShopSceneCache.Current.ItemVolumes where (Object)(object)volume != (Object)null && ((Component)volume).gameObject.activeInHierarchy where !((Object)volume).name.StartsWith("MoreStandsForShops", StringComparison.OrdinalIgnoreCase) where (Object)(object)((Component)volume).GetComponent() == (Object)null where IsTableVolumeType(volume.itemVolume) where GetTransformPath(((Component)volume).transform).IndexOf("/ITEM STANDS/ITEMS/", StringComparison.OrdinalIgnoreCase) >= 0 select volume; } private static bool IsTableVolumeType(itemVolume itemVolume) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)itemVolume <= 2 || (int)itemVolume == 5) { return true; } return false; } private static List BuildLogicalSlots(List volumes) { //IL_0024: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (ItemVolume volume in volumes) { Vector2 point = new Vector2(((Component)volume).transform.localPosition.x, ((Component)volume).transform.localPosition.z); TableLogicalSlot tableLogicalSlot = list.FirstOrDefault((TableLogicalSlot existing) => Vector2.Distance(existing.Center, point) <= 0.03f); if (tableLogicalSlot == null) { tableLogicalSlot = new TableLogicalSlot(); list.Add(tableLogicalSlot); } tableLogicalSlot.Add(volume, point); } return list; } private static void RewriteLogicalTableSlot(Transform tableRoot, TableLogicalSlot slot, string groupId, ref int reused, ref int created, ref int disabled) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) HashSet used = new HashSet(); itemVolume[] tableSlotTypes = TableSlotTypes; foreach (itemVolume val in tableSlotTypes) { ItemVolume val2 = PickReusableVolume(slot, val, used); TableVolumePose pose = BuildPoseForType(slot, val); if ((Object)(object)val2 != (Object)null) { ApplyPose(((Component)val2).transform, pose); val2.volumes = new List(pose.Source.Volumes); MarkMultiSizeVolume(val2, groupId, val); used.Add(val2); reused++; } else { CreateMultiSizeVolume(tableRoot, pose, groupId, val); created++; } if (Plugin.DebugLogs.Value) { ManualLogSource log = Plugin.Log; string[] obj = new string[5] { $"[ShelfTableRewrite] Prepared table slot variant: group={groupId}, type={val}, ", null, null, null, null }; string arg = FormatVector(pose.LocalPosition); Quaternion localRotation = pose.LocalRotation; obj[1] = $"local={arg}, yaw={((Quaternion)(ref localRotation)).eulerAngles.y:F1}, "; obj[2] = "template="; obj[3] = pose.Source.Name; obj[4] = "."; log.LogInfo((object)string.Concat(obj)); } } foreach (ItemVolume item in slot.Volumes.Where((ItemVolume volume) => !used.Contains(volume))) { ((Behaviour)item).enabled = false; ((Component)item).gameObject.SetActive(false); disabled++; } } private static ItemVolume PickReusableVolume(TableLogicalSlot slot, itemVolume itemVolume, HashSet used) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 ItemVolume val = ((IEnumerable)slot.Volumes).FirstOrDefault((Func)((ItemVolume volume) => !used.Contains(volume) && volume.itemVolume == itemVolume)); if ((Object)(object)val != (Object)null) { return val; } if ((int)itemVolume == 1) { return ((IEnumerable)slot.Volumes).FirstOrDefault((Func)((ItemVolume volume) => !used.Contains(volume))); } return null; } private static TableVolumePose BuildPoseForType(TableLogicalSlot slot, itemVolume itemVolume) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) TableVolumeTemplate tableVolumeTemplate = FindNearestTemplate(slot, itemVolume) ?? FindNearestTemplate(slot, (itemVolume)1) ?? new TableVolumeTemplate(slot.Volumes[0]); Vector3 localPosition = tableVolumeTemplate.LocalPosition; return new TableVolumePose(tableVolumeTemplate, new Vector3(slot.Center.x, localPosition.y, slot.Center.y), tableVolumeTemplate.LocalRotation, tableVolumeTemplate.LocalScale); } private static TableVolumeTemplate FindNearestTemplate(TableLogicalSlot slot, itemVolume itemVolume) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return (from volume in slot.AllTableVolumes where volume.ItemVolume == itemVolume orderby Vector2.Distance(slot.Center, new Vector2(volume.LocalPosition.x, volume.LocalPosition.z)) select volume).FirstOrDefault(); } private static void ApplyPose(Transform transform, TableVolumePose pose) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) transform.localPosition = pose.LocalPosition; transform.localRotation = pose.LocalRotation; transform.localScale = pose.LocalScale; } private static ItemVolume CreateVolumeSlot(Transform parent, string name, itemVolume itemVolume, Vector3 localPosition, MoreStandsShelfZone? zone = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localRotation = Quaternion.identity; ItemVolume obj = val.AddComponent(); obj.itemVolume = itemVolume; obj.itemSecretShopType = (itemSecretShopType)0; if (zone.HasValue) { val.AddComponent().Zone = zone.Value; } return obj; } private static IEnumerable FindItemStandRoots(string exactName) { return from transform in ShopSceneCache.Current.Transforms where (Object)(object)transform != (Object)null && ((Component)transform).gameObject.activeInHierarchy where string.Equals(((Object)transform).name, exactName, StringComparison.OrdinalIgnoreCase) where GetTransformPath(transform).IndexOf("/ITEM STANDS/", StringComparison.OrdinalIgnoreCase) >= 0 select transform; } private static string GetTransformPath(Transform transform) { return ShopSceneCache.Current.GetTransformPath(transform); } private static string FormatVector(Vector3 vector) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return $"({vector.x:F3}, {vector.y:F3}, {vector.z:F3})"; } static VanillaShelfTableRewriter() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_014b: Unknown result type (might be due to invalid IL or missing references) itemVolume[] array = new itemVolume[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); TableSlotTypes = (itemVolume[])(object)array; HealthSlotPositions = (Vector3[])(object)new Vector3[5] { new Vector3(-0.72f, 1.68f, 0.5f), new Vector3(-0.36f, 1.68f, 0.5f), new Vector3(0f, 1.68f, 0.5f), new Vector3(0.36f, 1.68f, 0.5f), new Vector3(0.72f, 1.68f, 0.5f) }; LowerSmallSlotPositions = (Vector3[])(object)new Vector3[6] { new Vector3(-0.75f, 1.18f, 0.5f), new Vector3(-0.45f, 1.18f, 0.5f), new Vector3(-0.15f, 1.18f, 0.5f), new Vector3(0.15f, 1.18f, 0.5f), new Vector3(0.45f, 1.18f, 0.5f), new Vector3(0.75f, 1.18f, 0.5f) }; } } } namespace MoreStandsForShops.Patches { [HarmonyPatch(typeof(PunManager))] internal static class PunManagerPatch { [HarmonyPrefix] [HarmonyPatch("ShopPopulateItemVolumes")] private static void ShopPopulateItemVolumesPrefix(PunManager __instance) { if (Plugin.EnableMod.Value && SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { ShopSpawnFlow.PrepareBeforeVanillaPopulate(__instance); } } [HarmonyPostfix] [HarmonyPatch("ShopPopulateItemVolumes")] private static void ShopPopulateItemVolumesPostfix() { if (Plugin.EnableMod.Value && SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { UpgradeStandSpawner.SchedulePostPopulateCartOverlapRecheck(); } } [HarmonyPrefix] [HarmonyPatch("SpawnShopItem")] private static bool SpawnShopItemPrefix(PunManager __instance, ItemVolume itemVolume, List itemList, ref int spawnCount, bool isSecret, ref bool __result) { if (ShopSpawnFlow.IsCallingVanilla) { return true; } if (!Plugin.EnableMod.Value || !SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsShop()) { return true; } if (ShopSpawnFlow.TryHandleSpawnShopItem(__instance, itemVolume, itemList, ref spawnCount, isSecret, out var result)) { __result = result; return false; } LogTableMultiSizeSpawnCandidate(itemVolume, itemList); return true; } [HarmonyPostfix] [HarmonyPatch("SpawnShopItem")] private static void SpawnShopItemPostfix(ItemVolume itemVolume, bool __result) { if (!ShopSpawnFlow.IsCallingVanilla && Plugin.EnableMod.Value && SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { ShopSpawnFlow.NoteSpawnShopItemResult(itemVolume, __result); } } private static void LogTableMultiSizeSpawnCandidate(ItemVolume itemVolume, List itemList) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.DebugLogs.Value || (Object)(object)itemVolume == (Object)null || itemList == null) { return; } MoreStandsMultiSizeVolume component = ((Component)itemVolume).GetComponent(); if (!((Object)(object)component == (Object)null) && !string.IsNullOrEmpty(component.GroupId)) { Item val = PredictVanillaSelectedItem(itemVolume, itemList); if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)("[MultiSizeSlot] Vanilla candidate missing: group=" + component.GroupId + ", " + $"slotVolume={itemVolume.itemVolume}, local={((Component)itemVolume).transform.localPosition}, " + $"world={((Component)itemVolume).transform.position}.")); } else { Plugin.Log.LogInfo((object)("[MultiSizeSlot] Vanilla candidate: group=" + component.GroupId + ", " + $"slotVolume={itemVolume.itemVolume}, item={ItemName(val)}, " + $"itemVolume={val.itemVolume}, local={((Component)itemVolume).transform.localPosition}, " + $"world={((Component)itemVolume).transform.position}, yaw={((Component)itemVolume).transform.eulerAngles.y:F1}.")); } } } private static Item PredictVanillaSelectedItem(ItemVolume itemVolume, List itemList) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) for (int num = itemList.Count - 1; num >= 0; num--) { Item val = itemList[num]; if ((Object)(object)val != (Object)null && val.itemVolume == itemVolume.itemVolume) { return val; } } return null; } private static string ItemName(Item item) { if ((Object)(object)item == (Object)null) { return ""; } if (!string.IsNullOrWhiteSpace(item.itemName)) { return item.itemName; } return ((Object)item).name; } } [HarmonyPatch(typeof(RunManager))] internal static class RunStateResetPatch { [HarmonyPostfix] [HarmonyPatch("ChangeLevel")] private static void ChangeLevelPostfix() { ResetSessionState("level change"); } [HarmonyPostfix] [HarmonyPatch("LeaveToMainMenu")] private static void LeaveToMainMenuPostfix() { ResetSessionState("leave to main menu"); } private static void ResetSessionState(string reason) { ClientShopLayoutApplier.Reset(); ShopItemLimitPlanner.ResetForSession(); ShopSceneCache.Clear(); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)("[RunStateResetPatch] Session state reset on " + reason + ".")); } } } [HarmonyPatch(typeof(ShopManager))] internal static class ShopManagerPatch { [HarmonyPrefix] [HarmonyPatch("ShopInitialize")] private static void ShopInitializePrefix(ShopManager __instance) { if (!SemiFunc.RunIsShop() || (Object)(object)StatsManager.instance == (Object)null) { return; } if (!Plugin.EnableMod.Value) { Plugin.Log.LogInfo((object)"[ShopManagerPatch] Mod disabled by config; shop customizations skipped."); return; } bool num = SemiFunc.IsMasterClientOrSingleplayer(); if (num) { ShopSpawnFlow.ResetForShop(); } if (!num) { Plugin.Log.LogInfo((object)"[ShopManagerPatch] Client detected; waiting for host shop layout."); ClientShopLayoutApplier.ApplyWhenReady(); return; } Plugin.Log.LogInfo((object)"[ShopManagerPatch] Running host shop initialization customizations..."); if (SemiFunc.IsMultiplayer()) { ShopLayoutSync.Clear(); } RunCustomizationStep("UpgradeStandSpawner", delegate { UpgradeStandSpawner.TrySpawn(out var _); }); RunCustomizationStep("DroneCrystalStandSpawner", delegate { DroneCrystalStandSpawner.TrySpawn(out var _); }); RunCustomizationStep("VanillaShelfTableRewriter", VanillaShelfTableRewriter.Apply); RunCustomizationStep("ShopItemLimitPlanner", ShopItemLimitPlanner.ApplyConfiguredItemLimits); if (SemiFunc.IsMultiplayer()) { ShopLayoutSync.MarkReady(); } Plugin.Log.LogInfo((object)"[ShopManagerPatch] Customization complete."); } private static void RunCustomizationStep(string stepName, Action action) { try { action(); } catch (Exception arg) { Plugin.Log.LogError((object)$"[ShopManagerPatch] {stepName} failed; continuing vanilla shop initialization.\n{arg}"); } } [HarmonyPrefix] [HarmonyPriority(0)] [HarmonyPatch("GetAllItemsFromStatsManager")] private static void GetAllItemsFromStatsManagerPrefix(ShopManager __instance) { if (Plugin.EnableMod.Value && SemiFunc.IsMasterClientOrSingleplayer()) { ShopItemLimitPlanner.ApplyConfiguredItemLimits(); } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch("GetAllItemsFromStatsManager")] private static void GetAllItemsFromStatsManagerPostfix(ShopManager __instance) { if (Plugin.EnableMod.Value && SemiFunc.IsMasterClientOrSingleplayer()) { ShopPoolPlanner.PreparePools(__instance); ShopBudgetPlanner.ApplyConfiguredBudgets(__instance); } } } internal static class ShopSpawnFlow { internal static bool IsCallingVanilla => VanillaShopItemSpawner.IsCallingVanilla; internal static void ResetForShop() { ShopSceneCache.Rebuild(); ShelfSpawnController.ResetForShop(); MultiSizeSlotController.ResetForShop(); } internal static void PrepareBeforeVanillaPopulate(PunManager punManager) { ShelfSpawnController.PrepareVolumesForPopulate(punManager); ShopBudgetPlanner.ApplyFillAllShopSlotBudget(ShopManager.instance); } internal static bool TryHandleSpawnShopItem(PunManager punManager, ItemVolume itemVolume, List itemList, ref int spawnCount, bool isSecret, out bool result) { if (ShelfSpawnController.TryHandleSpawnShopItem(punManager, itemVolume, itemList, ref spawnCount, isSecret, out result)) { return true; } if (MultiSizeSlotController.TrySkipHandledSlot(itemVolume, out result)) { return true; } return false; } internal static void NoteSpawnShopItemResult(ItemVolume itemVolume, bool spawned) { MultiSizeSlotController.NoteSpawnResult(itemVolume, spawned); } } } namespace MoreStandsForShops.Network { internal sealed class ClientShopLayoutApplier : MonoBehaviour { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; _isApplying = true; 5__2 = 1; break; case 1: <>1__state = -1; 5__2++; break; } if (5__2 <= 40) { bool flag = ShopLayoutSync.IsReady(); int sequence = ShopLayoutSync.GetSequence(); if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ClientShopLayoutApplier] Waiting layout: attempt={5__2}/{40}, ready={flag}, sequence={sequence}, lastApplied={_lastAppliedSequence}."); } if (flag && sequence != _lastAppliedSequence) { ApplyNow(sequence); _isApplying = false; return false; } <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 1; return true; } _isApplying = false; Plugin.Log.LogWarning((object)$"[ClientShopLayoutApplier] Host shop layout did not become ready with a new sequence in time. lastApplied={_lastAppliedSequence}, current={ShopLayoutSync.GetSequence()}, ready={ShopLayoutSync.IsReady()}."); 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(); } } private const int MaxAttempts = 40; private const float RetryDelay = 0.25f; private static ClientShopLayoutApplier _instance; private static bool _isApplying; private static int _lastAppliedSequence; internal static void Reset() { if ((Object)(object)_instance != (Object)null) { ((MonoBehaviour)_instance).StopAllCoroutines(); } _isApplying = false; } internal static void ApplyWhenReady() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (!_isApplying) { if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("MoreStandsForShops_ClientShopLayoutApplier"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); } ((MonoBehaviour)_instance).StartCoroutine(_instance.ApplyRoutine()); } } [IteratorStateMachine(typeof(d__7))] private IEnumerator ApplyRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0); } private static void ApplyNow(int sequence) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) bool flag = false; if (ShopLayoutSync.TryGetUpgradeStand(out var layout)) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ClientShopLayoutApplier] Upgrade layout received: variant={layout.VariantId}, slots={layout.UpgradeSlotCount}."); } flag |= UpgradeStandSpawner.SpawnNetworkVisual("room-layout", layout.VariantId, layout.Position, layout.Rotation, layout.ParentPath, layout.DisabledPaths); } if (ShopLayoutSync.TryGetDroneCrystalShelf(out var layout2)) { if (Plugin.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"[ClientShopLayoutApplier] Shelf layout received: droneSlots={layout2.DroneSlotCount}, crystalSlots={layout2.CrystalSlotCount}."); } flag |= DroneCrystalStandSpawner.SpawnNetworkVisual("room-layout", layout2.DisabledPaths); } _lastAppliedSequence = sequence; if (Plugin.DebugLogs.Value) { if (flag) { Plugin.Log.LogInfo((object)"[ClientShopLayoutApplier] Applied host shop layout."); } else { Plugin.Log.LogInfo((object)"[ClientShopLayoutApplier] Host shop layout was ready but contained no custom stands."); } } } } internal sealed class DroneCrystalShelfLayout { internal bool Enabled; internal int DroneSlotCount; internal int CrystalSlotCount; internal string[] DisabledPaths; } internal static class ShopLayoutSync { private const string UpgradeActiveKey = "MSFS.Upgrade.Active"; private const string UpgradeVariantKey = "MSFS.Upgrade.Variant"; private const string UpgradePositionKey = "MSFS.Upgrade.Position"; private const string UpgradeRotationKey = "MSFS.Upgrade.Rotation"; private const string UpgradeParentKey = "MSFS.Upgrade.Parent"; private const string UpgradeDisabledKey = "MSFS.Upgrade.Disabled"; private const string ShelfActiveKey = "MSFS.Shelf.Active"; private const string ShelfDroneSlotCountKey = "MSFS.Shelf.DroneSlotCount"; private const string ShelfCrystalSlotCountKey = "MSFS.Shelf.CrystalSlotCount"; private const string ShelfDisabledKey = "MSFS.Shelf.Disabled"; private const string LayoutReadyKey = "MSFS.Layout.Ready"; private const string LayoutSequenceKey = "MSFS.Layout.Sequence"; private const string UpgradeSlotCountKey = "MSFS.Upgrade.SlotCount"; private static int _nextSequence; internal static void Clear() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_002e: 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_0043: Expected O, but got Unknown //IL_0043: 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_0058: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_00f3: Expected O, but got Unknown if (CanWrite()) { Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"MSFS.Upgrade.Active", (object)false); ((Dictionary)val).Add((object)"MSFS.Upgrade.Variant", (object)string.Empty); ((Dictionary)val).Add((object)"MSFS.Upgrade.Position", (object)Vector3.zero); ((Dictionary)val).Add((object)"MSFS.Upgrade.Rotation", (object)Quaternion.identity); ((Dictionary)val).Add((object)"MSFS.Upgrade.Parent", (object)string.Empty); ((Dictionary)val).Add((object)"MSFS.Upgrade.Disabled", (object)string.Empty); ((Dictionary)val).Add((object)"MSFS.Upgrade.SlotCount", (object)0); ((Dictionary)val).Add((object)"MSFS.Shelf.Active", (object)false); ((Dictionary)val).Add((object)"MSFS.Shelf.DroneSlotCount", (object)0); ((Dictionary)val).Add((object)"MSFS.Shelf.CrystalSlotCount", (object)0); ((Dictionary)val).Add((object)"MSFS.Shelf.Disabled", (object)string.Empty); ((Dictionary)val).Add((object)"MSFS.Layout.Ready", (object)false); ((Dictionary)val).Add((object)"MSFS.Layout.Sequence", (object)NextSequence()); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)string.Format("[ShopLayoutSync] Cleared shop layout. sequence={0}.", ReadInt(val2, "MSFS.Layout.Sequence"))); } } internal static void MarkReady() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0036: Expected O, but got Unknown if (CanWrite()) { int num = NextSequence(); Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"MSFS.Layout.Ready", (object)true); ((Dictionary)val).Add((object)"MSFS.Layout.Sequence", (object)num); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)$"[ShopLayoutSync] Marked shop layout ready. sequence={num}."); } } internal static void SetUpgradeStand(UpgradeStandLayout layout) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0056: 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_006c: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00b3: Expected O, but got Unknown if (CanWrite() && layout != null) { Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"MSFS.Upgrade.Active", (object)layout.Enabled); ((Dictionary)val).Add((object)"MSFS.Upgrade.SlotCount", (object)layout.UpgradeSlotCount); ((Dictionary)val).Add((object)"MSFS.Upgrade.Variant", (object)(layout.VariantId ?? string.Empty)); ((Dictionary)val).Add((object)"MSFS.Upgrade.Position", (object)layout.Position); ((Dictionary)val).Add((object)"MSFS.Upgrade.Rotation", (object)layout.Rotation); ((Dictionary)val).Add((object)"MSFS.Upgrade.Parent", (object)(layout.ParentPath ?? string.Empty)); ((Dictionary)val).Add((object)"MSFS.Upgrade.Disabled", (object)JoinPaths(layout.DisabledPaths)); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); ManualLogSource log = Plugin.Log; object[] obj = new object[4] { layout.Enabled, layout.VariantId, layout.UpgradeSlotCount, null }; string[] disabledPaths = layout.DisabledPaths; obj[3] = ((disabledPaths != null) ? disabledPaths.Length : 0); log.LogInfo((object)string.Format("[ShopLayoutSync] Stored upgrade stand layout: enabled={0}, variant={1}, slots={2}, disabledPaths={3}.", obj)); } } internal static bool TryGetUpgradeStand(out UpgradeStandLayout layout) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_007c: Unknown result type (might be due to invalid IL or missing references) layout = null; if (!CanRead()) { return false; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (!ReadBool(customProperties, "MSFS.Upgrade.Active")) { return false; } layout = new UpgradeStandLayout { Enabled = ReadBool(customProperties, "MSFS.Upgrade.Active"), UpgradeSlotCount = ReadInt(customProperties, "MSFS.Upgrade.SlotCount"), VariantId = ReadString(customProperties, "MSFS.Upgrade.Variant"), Position = ReadVector3(customProperties, "MSFS.Upgrade.Position"), Rotation = ReadQuaternion(customProperties, "MSFS.Upgrade.Rotation"), ParentPath = ReadString(customProperties, "MSFS.Upgrade.Parent"), DisabledPaths = SplitPaths(ReadString(customProperties, "MSFS.Upgrade.Disabled")) }; return true; } internal static void SetDroneCrystalShelf(DroneCrystalShelfLayout layout) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0069: Expected O, but got Unknown if (CanWrite() && layout != null) { Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"MSFS.Shelf.Active", (object)layout.Enabled); ((Dictionary)val).Add((object)"MSFS.Shelf.DroneSlotCount", (object)layout.DroneSlotCount); ((Dictionary)val).Add((object)"MSFS.Shelf.CrystalSlotCount", (object)layout.CrystalSlotCount); ((Dictionary)val).Add((object)"MSFS.Shelf.Disabled", (object)JoinPaths(layout.DisabledPaths)); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); ManualLogSource log = Plugin.Log; object[] obj = new object[4] { layout.Enabled, layout.DroneSlotCount, layout.CrystalSlotCount, null }; string[] disabledPaths = layout.DisabledPaths; obj[3] = ((disabledPaths != null) ? disabledPaths.Length : 0); log.LogInfo((object)string.Format("[ShopLayoutSync] Stored drone/crystal shelf layout: enabled={0}, droneSlots={1}, crystalSlots={2}, disabledPaths={3}.", obj)); } } internal static bool TryGetDroneCrystalShelf(out DroneCrystalShelfLayout layout) { layout = null; if (!CanRead()) { return false; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (!ReadBool(customProperties, "MSFS.Shelf.Active")) { return false; } layout = new DroneCrystalShelfLayout { Enabled = ReadBool(customProperties, "MSFS.Shelf.Active"), DroneSlotCount = ReadInt(customProperties, "MSFS.Shelf.DroneSlotCount"), CrystalSlotCount = ReadInt(customProperties, "MSFS.Shelf.CrystalSlotCount"), DisabledPaths = SplitPaths(ReadString(customProperties, "MSFS.Shelf.Disabled")) }; return true; } internal static bool IsReady() { if (!CanRead()) { return false; } return ReadBool(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties, "MSFS.Layout.Ready"); } internal static int GetSequence() { if (!CanRead()) { return 0; } return ReadInt(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties, "MSFS.Layout.Sequence"); } private static bool CanWrite() { if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) { return PhotonNetwork.CurrentRoom != null; } return false; } private static bool CanRead() { if (PhotonNetwork.InRoom) { return PhotonNetwork.CurrentRoom != null; } return false; } private static bool ReadBool(Hashtable props, string key) { bool flag = default(bool); int num; if (((Dictionary)(object)props).TryGetValue((object)key, out object value)) { if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static int ReadInt(Hashtable props, string key) { if (((Dictionary)(object)props).TryGetValue((object)key, out object value) && value is int) { return (int)value; } return 0; } private static string ReadString(Hashtable props, string key) { if (!((Dictionary)(object)props).TryGetValue((object)key, out object value) || !(value is string result)) { return string.Empty; } return result; } private static Vector3 ReadVector3(Hashtable props, string key) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (((Dictionary)(object)props).TryGetValue((object)key, out object value) && value is Vector3) { return (Vector3)value; } return Vector3.zero; } private static Quaternion ReadQuaternion(Hashtable props, string key) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (((Dictionary)(object)props).TryGetValue((object)key, out object value) && value is Quaternion) { return (Quaternion)value; } return Quaternion.identity; } private static string JoinPaths(string[] paths) { if (paths != null) { return string.Join("\n", paths); } return string.Empty; } private static string[] SplitPaths(string value) { if (!string.IsNullOrWhiteSpace(value)) { return value.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); } return Array.Empty(); } private static int NextSequence() { _nextSequence++; if (_nextSequence <= 0) { _nextSequence = 1; } return _nextSequence; } } internal sealed class UpgradeStandLayout { internal bool Enabled; internal string VariantId; internal Vector3 Position; internal Quaternion Rotation; internal string ParentPath; internal string[] DisabledPaths; internal int UpgradeSlotCount; } }