Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Shop Items Spawn in Level v1.7.20
REPO_Shop_Items_in_Level.dll
Decompiled 5 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("REPO_Shop_Items_in_Level")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.7.20.0")] [assembly: AssemblyInformationalVersion("1.7.20+2f095d29308799a97341ec4944d0353f59d39f44")] [assembly: AssemblyProduct("Shop Items spawn in Level")] [assembly: AssemblyTitle("REPO_Shop_Items_in_Level")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.7.20.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPO_Shop_Items_in_Level { public class UsedVolumeTracker : MonoBehaviour { } public class SpawnedItemTracker : MonoBehaviour { } [BepInPlugin("REPO_Shop_Items_in_Level", "Shop Items spawn in Level", "1.7.20")] [BepInProcess("REPO.exe")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(EnemyParent), "Despawn")] private class DespawnPatch { private static int GetEnemySpawnValuableCurrent(EnemyParent enemyParent) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown Enemy val = (Enemy)(AccessTools.Field(typeof(EnemyParent), "Enemy")?.GetValue(enemyParent)); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)("Failed to access Enemy from EnemyParent " + ((Object)enemyParent).name + ".")); return 0; } EnemyHealth val2 = (EnemyHealth)(AccessTools.Field(typeof(Enemy), "Health")?.GetValue(val)); if ((Object)(object)val2 == (Object)null) { Logger.LogWarning((object)("Failed to access Health from Enemy " + ((Object)enemyParent).name + ".")); return 0; } FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyHealth), "spawnValuableCurrent"); if (fieldInfo == null) { Logger.LogWarning((object)("Field spawnValuableCurrent not found in EnemyHealth for enemy " + ((Object)enemyParent).name + ".")); return 0; } return (int)fieldInfo.GetValue(val2); } private static void Prefix(EnemyParent __instance, out int __state) { __state = GetEnemySpawnValuableCurrent(__instance); } private static void Postfix(EnemyParent __instance, int __state) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer() || !SpawnHealthPacksFromEnemies.Value || GetEnemySpawnValuableCurrent(__instance) <= __state) { return; } Logger.LogInfo((object)("Enemy " + ((Object)__instance).name + " spawned a valuable!")); Item item; if (Random.Range(0f, 100f) >= HealthPackDropChance.Value) { Logger.LogInfo((object)$"Health pack spawn roll failed (chance: {HealthPackDropChance.Value}%)"); } else if (GetRandomItemOfType((itemType)8, out item)) { Enemy val = (Enemy)(AccessTools.Field(typeof(EnemyParent), "Enemy")?.GetValue(__instance)); Transform val2 = val.CustomValuableSpawnTransform; if (!Object.op_Implicit((Object)(object)val2)) { val2 = val.CenterTransform; } Vector3 position = val2.position + new Vector3(0f, 1f, 0f); Quaternion identity = Quaternion.identity; SpawnItem(item, position, identity); } } } internal static ManualLogSource Logger; internal static ConfigEntry<bool> SpawnUpgradeItems; internal static ConfigEntry<bool> MapHideUpgradeItems; internal static ConfigEntry<float> UpgradeItemSpawnChance; internal static ConfigEntry<bool> UseShopPriceForUpgradeItems; internal static ConfigEntry<bool> SpawnDroneItems; internal static ConfigEntry<bool> MapHideDroneItems; internal static ConfigEntry<float> DroneItemSpawnChance; internal static ConfigEntry<bool> UseShopPriceForDroneItems; internal static ConfigEntry<bool> SpawnHealthPacksFromEnemies; internal static ConfigEntry<float> HealthPackDropChance; internal static List<ConfigEntry<bool>> DisallowedItems; private Harmony harmony; public static Plugin Instance { get; private set; } private void Awake() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin REPO_Shop_Items_in_Level is loaded!"); harmony = new Harmony("REPO_Shop_Items_in_Level"); harmony.PatchAll(typeof(Plugin)); harmony.PatchAll(typeof(DespawnPatch)); Logger.LogInfo((object)"Harmony patches applied!"); SpawnUpgradeItems = ((BaseUnityPlugin)this).Config.Bind<bool>("UpgradeItems", "SpawnUpgradeItems", true, new ConfigDescription("Whether upgrade items can spawn in levels", (AcceptableValueBase)null, Array.Empty<object>())); MapHideUpgradeItems = ((BaseUnityPlugin)this).Config.Bind<bool>("UpgradeItems", "MapHideShopUpgradeItems", true, new ConfigDescription("(Client) Whether upgrade items are hidden on the map", (AcceptableValueBase)null, Array.Empty<object>())); UpgradeItemSpawnChance = ((BaseUnityPlugin)this).Config.Bind<float>("UpgradeItems", "UpgradeItemSpawnChance", 2.5f, new ConfigDescription("% chance for an upgrade item to spawn", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); UseShopPriceForUpgradeItems = ((BaseUnityPlugin)this).Config.Bind<bool>("UpgradeItems", "UseShopPriceForItemSelection", true, new ConfigDescription("If ON: Cheaper upgrade items appear more often. If OFF: All upgrade items have equal chance.", (AcceptableValueBase)null, Array.Empty<object>())); SpawnDroneItems = ((BaseUnityPlugin)this).Config.Bind<bool>("DroneItems", "SpawnDroneItems", true, new ConfigDescription("Whether drone items can spawn in levels", (AcceptableValueBase)null, Array.Empty<object>())); MapHideDroneItems = ((BaseUnityPlugin)this).Config.Bind<bool>("DroneItems", "MapHideDroneItems", true, new ConfigDescription("(Client) Whether drone items are hidden on the map", (AcceptableValueBase)null, Array.Empty<object>())); DroneItemSpawnChance = ((BaseUnityPlugin)this).Config.Bind<float>("DroneItems", "DroneItemsSpawnChance", 0.95f, new ConfigDescription("% chance for a drone item to spawn", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); UseShopPriceForDroneItems = ((BaseUnityPlugin)this).Config.Bind<bool>("DroneItems", "UseShopPriceForItemSelection", true, new ConfigDescription("If ON: Cheaper drone items appear more often. If OFF: All drone items have equal chance.", (AcceptableValueBase)null, Array.Empty<object>())); SpawnHealthPacksFromEnemies = ((BaseUnityPlugin)this).Config.Bind<bool>("HealthPacks", "SpawnHealthPacksFromEnemies", true, new ConfigDescription("Whether health packs can spawn when enemies die", (AcceptableValueBase)null, Array.Empty<object>())); HealthPackDropChance = ((BaseUnityPlugin)this).Config.Bind<float>("HealthPacks", "HealthPackDropChance", 100f, new ConfigDescription("% chance for a health pack to spawn when an enemy dies", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); } [HarmonyPatch(typeof(MainMenuOpen), "Awake")] [HarmonyPostfix] public static void MainMenuOpen_Awake_Postfix(StatsManager __instance) { //IL_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Invalid comparison between Unknown and I4 //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (DisallowedItems != null) { return; } Logger.LogInfo((object)"Initializing disallowed items list"); DisallowedItems = new List<ConfigEntry<bool>>(); foreach (Item value in StatsManager.instance.itemDictionary.Values) { itemType itemType = value.itemType; itemType val = itemType; ConfigEntry<bool> val2; if ((int)val != 0) { if ((int)val != 3) { continue; } val2 = ((BaseUnityPlugin)Instance).Config.Bind<bool>("AllowedItems Upgrades", ((Object)value).name, true, new ConfigDescription("Whether this upgrade item can spawn in levels", (AcceptableValueBase)null, Array.Empty<object>())); } else { val2 = ((BaseUnityPlugin)Instance).Config.Bind<bool>("AllowedItems Drones", ((Object)value).name, true, new ConfigDescription("Whether this drone item can spawn in levels", (AcceptableValueBase)null, Array.Empty<object>())); } if (!val2.Value) { DisallowedItems.Add(val2); } } } private static bool GetRandomItemOfType(itemType itemType, out Item item) { //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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Invalid comparison between Unknown and I4 //IL_02c1: 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_00d3: Invalid comparison between Unknown and I4 //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) item = null; List<Item> list = (from i in StatsManager.instance.itemDictionary.Values where i.itemType == itemType where (Object)(object)i.value != (Object)null && i.value.valueMin > 0f where !DisallowedItems.Any((ConfigEntry<bool> cfg) => ((ConfigEntryBase)cfg).Definition.Key == ((Object)i).name && !cfg.Value) select i).ToList(); if (list.Count == 0) { Logger.LogWarning((object)$"GetRandomItemOfType: No valid items found for type {itemType} after filtering."); return false; } bool flag = false; itemType val = itemType; itemType val2 = val; if ((int)val2 != 0) { if ((int)val2 != 3) { if ((int)val2 == 8) { flag = true; } } else { flag = UseShopPriceForUpgradeItems.Value; } } else { flag = UseShopPriceForDroneItems.Value; } if (flag) { float num = list.Sum((Item i) => 1f / i.value.valueMin); if (num <= 0f || float.IsNaN(num) || float.IsInfinity(num)) { Logger.LogWarning((object)($"GetRandomItemOfType: Invalid total weight {num} for type {itemType}. " + "This may indicate an issue with item values or weights.")); return false; } float num2 = Random.Range(0f, num); foreach (Item item2 in list) { float num3 = 1f / item2.value.valueMin; num2 -= num3; if (num2 <= 0f) { item = item2; break; } } if ((Object)(object)item == (Object)null) { Logger.LogWarning((object)($"GetRandomItemOfType: Weighted selection loop for type {itemType} completed unexpectedly " + "without selecting an item. This may indicate a precision issue.")); return false; } float num4 = 1f / item.value.valueMin / num * 100f; Logger.LogInfo((object)$"Selecting {((Object)item).name} at a chance of {num4:F2}% compared to others of type {itemType} (based on shop price)"); } else { int index = Random.Range(0, list.Count); item = list[index]; Logger.LogInfo((object)$"Selecting {((Object)item).name} at a chance of {100f / (float)list.Count:F2}% compared to others of type {itemType} (equal chance)"); } return true; } private static bool HasValuablePropSwitch(ValuableVolume volume) { return (Object)(object)((Component)((Component)volume).transform).GetComponentInParent<ValuablePropSwitch>() != (Object)null; } private static bool ShouldSpawnItem(ValuableVolume volume, out itemType? itemType, out bool hasSwitch) { //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_0024: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 itemType = null; hasSwitch = HasValuablePropSwitch(volume); if (hasSwitch) { return false; } Type volumeType = volume.VolumeType; Type val = volumeType; if ((int)val != 0) { if ((int)val == 1) { if (!SpawnDroneItems.Value) { return false; } itemType = (itemType)0; return Random.Range(0f, 100f) <= DroneItemSpawnChance.Value; } return false; } if (!SpawnUpgradeItems.Value) { return false; } itemType = (itemType)3; return Random.Range(0f, 100f) <= UpgradeItemSpawnChance.Value; } private static GameObject SpawnItem(Item item, Vector3 position, Quaternion rotation) { //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_001b: 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) GameObject val = ((!SemiFunc.IsMultiplayer()) ? Object.Instantiate<GameObject>(item.prefab.Prefab, position, rotation) : PhotonNetwork.Instantiate("Items/" + ((Object)item).name, position, rotation, (byte)0, (object[])null)); val.AddComponent<SpawnedItemTracker>(); return val; } private static bool RandomItemSpawn(ValuableVolume volume) { //IL_002e: 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_005a: Unknown result type (might be due to invalid IL or missing references) if (!ShouldSpawnItem(volume, out var itemType, out var _)) { return false; } if (!itemType.HasValue) { return false; } if (!GetRandomItemOfType(itemType.Value, out var item)) { return false; } SpawnItem(item, ((Component)volume).transform.position, ((Component)volume).transform.rotation); return true; } [HarmonyPatch(typeof(ValuableDirector), "Spawn")] [HarmonyPrefix] public static void ValuableDirector_Spawn_Prefix(GameObject _valuable, ValuableVolume _volume, string _path) { ((Component)_volume).gameObject.AddComponent<UsedVolumeTracker>(); } [HarmonyPatch(typeof(ValuableDirector), "VolumesAndSwitchSetup")] [HarmonyPostfix] public static void ValuableDirector_VolumesAndSwitchSetup_Postfix(ValuableDirector __instance) { if (!SemiFunc.RunIsLevel()) { return; } IEnumerable<ValuableVolume> enumerable = from volume in Object.FindObjectsOfType<ValuableVolume>(false).ToList() where (Object)(object)((Component)volume).gameObject.GetComponent<UsedVolumeTracker>() == (Object)null where !HasValuablePropSwitch(volume) select volume; Logger.LogInfo((object)$"Found {enumerable.Count()} potential volumes to spawn items in"); Logger.LogInfo((object)$"Upgrade item spawn chance: {UpgradeItemSpawnChance.Value}% on {enumerable.Where((ValuableVolume volume) => (int)volume.VolumeType == 0).Count()} tiny volumes"); Logger.LogInfo((object)$"Drone item spawn chance: {DroneItemSpawnChance.Value}% on {enumerable.Where((ValuableVolume volume) => (int)volume.VolumeType == 1).Count()} small volumes"); int num = 0; foreach (ValuableVolume item in enumerable) { if (RandomItemSpawn(item)) { num++; } } Logger.LogInfo((object)$"Spawned {num} items in total"); } [HarmonyPatch(typeof(Map), "AddCustom")] [HarmonyPostfix] public static void Map_AddCustom_Postfix(MapCustom mapCustom) { //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) //IL_0032: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 ItemAttributes val = default(ItemAttributes); if (!SemiFunc.RunIsLevel() || !((Component)mapCustom).gameObject.TryGetComponent<ItemAttributes>(ref val)) { return; } itemType itemType = val.item.itemType; itemType val2 = itemType; if ((int)val2 != 0) { if ((int)val2 != 3 || !MapHideUpgradeItems.Value) { return; } } else if (!MapHideDroneItems.Value) { return; } ((Component)mapCustom.mapCustomEntity).gameObject.SetActive(false); } [HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInHaulList")] [HarmonyPostfix] public static void ExtractionPoint_DestroyAllPhysObjectsInHaulList_Postfix(ExtractionPoint __instance) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } List<GameObject> list = (from tracker in Object.FindObjectsOfType<SpawnedItemTracker>(false) select ((Component)tracker).gameObject).ToList(); foreach (GameObject item in list) { RoomVolumeCheck component = item.GetComponent<RoomVolumeCheck>(); if (!((Object)(object)component == (Object)null) && component.CurrentRooms.Any((RoomVolume room) => room.Extraction)) { ItemAttributes component2 = item.GetComponent<ItemAttributes>(); Logger.LogInfo((object)("Adding item " + component2.itemAssetName + " to purchased items")); StatsManager.instance.ItemPurchase(component2.itemAssetName); Logger.LogInfo((object)("Destroying spawned item " + ((Object)item).name + " in extraction point " + ((Object)__instance).name)); item.GetComponent<PhysGrabObject>().DestroyPhysGrabObject(); } } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "REPO_Shop_Items_in_Level"; public const string PLUGIN_NAME = "Shop Items spawn in Level"; public const string PLUGIN_VERSION = "1.7.20"; } }