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.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(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPO_All_Shop_Items_in_Level { public class UsedVolumeTracker : MonoBehaviour { } public class SpawnedItemTracker : MonoBehaviour { } [BepInPlugin("REPO_All_Shop_Items_in_Level", "ALL Shop Items spawn in Level", "1.7.23")] [BepInProcess("REPO.exe")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(EnemyParent), "Despawn")] private class DespawnPatch { private static int GetSpawnValuableCurrent(EnemyParent ep) { object? obj = AccessTools.Field(typeof(EnemyParent), "Enemy")?.GetValue(ep); Enemy val = (Enemy)((obj is Enemy) ? obj : null); if ((Object)(object)val == (Object)null) { return 0; } object? obj2 = AccessTools.Field(typeof(Enemy), "Health")?.GetValue(val); EnemyHealth val2 = (EnemyHealth)((obj2 is EnemyHealth) ? obj2 : null); if ((Object)(object)val2 == (Object)null) { return 0; } FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyHealth), "spawnValuableCurrent"); return (!(fieldInfo == null)) ? ((int)fieldInfo.GetValue(val2)) : 0; } private static void Prefix(EnemyParent __instance, out int __state) { __state = GetSpawnValuableCurrent(__instance); } private static void Postfix(EnemyParent __instance, int __state) { //IL_00bc: 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_00c6: 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) if (SemiFunc.IsMasterClientOrSingleplayer() && SpawnHealthPacksFromEnemies.Value && GetSpawnValuableCurrent(__instance) > __state && !(Random.Range(0f, 100f) > HealthPackDropChance.Value) && GetRandomItemOfType((itemType)8, out var item)) { object? obj = AccessTools.Field(typeof(EnemyParent), "Enemy")?.GetValue(__instance); Enemy val = (Enemy)((obj is Enemy) ? obj : null); Transform val2 = (Object.op_Implicit((Object)(object)val.CustomValuableSpawnTransform) ? val.CustomValuableSpawnTransform : val.CenterTransform); SpawnItem(item, val2.position + Vector3.up, Quaternion.identity); } } } [HarmonyPatch] private class ValuableDirector_Spawn_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(ValuableDirector), "Spawn", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(ValuableDirector), "SpawnValuable", (Type[])null, (Type[])null); } [HarmonyPrefix] private static void Prefix(object[] __args) { ValuableVolume val = __args.OfType().FirstOrDefault(); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.AddComponent(); } } } [CompilerGenerated] private sealed class d__28 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private Dictionary.ValueCollection.Enumerator <>s__1; private Item 5__2; private int 5__3; private string
5__4; private string 5__5; private ConfigEntry 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>s__1 = default(Dictionary.ValueCollection.Enumerator); 5__2 = null;
5__4 = null; 5__5 = null; 5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected I4, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((Object)(object)StatsManager.instance == (Object)null || StatsManager.instance.itemDictionary == null || StatsManager.instance.itemDictionary.Count == 0) { <>2__current = null; <>1__state = 1; return true; } if (ItemAllowList != null) { return false; } Logger.LogInfo((object)"Initializing per-item allow list"); ItemAllowList = new Dictionary>(); <>s__1 = StatsManager.instance.itemDictionary.Values.GetEnumerator(); try { while (<>s__1.MoveNext()) { 5__2 = <>s__1.Current; 5__3 = (int)5__2.itemType;
5__4 = ((5__3 == 0) ? "6_AllowedItems_Drones" : ((5__3 == 3) ? "6_AllowedItems_Upgrades" : ((5__3 == 8) ? null : "6_AllowedItems_OtherShop"))); if (
5__4 != null) { 5__5 = ((Object)5__2).name; 5__6 = ((BaseUnityPlugin)Instance).Config.Bind(
5__4, 5__5, true, "Allow '" + 5__5 + "' to spawn"); ItemAllowList[5__5] = 5__6; DebugLog("Registered: " + 5__5);
5__4 = null; 5__5 = null; 5__6 = null; 5__2 = null; } } } finally { ((IDisposable)<>s__1).Dispose(); } <>s__1 = default(Dictionary.ValueCollection.Enumerator); Logger.LogInfo((object)$"Registered {ItemAllowList.Count} items"); 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(); } } internal static ManualLogSource Logger; internal static ConfigEntry DebugMode; internal static ConfigEntry SaveAllOnLevelComplete; internal static ConfigEntry SpawnUpgradeItems; internal static ConfigEntry UpgradeItemSpawnChance; internal static ConfigEntry MapHideUpgradeItems; internal static ConfigEntry UseShopPriceForUpgradeItems; internal static ConfigEntry SpawnDroneItems; internal static ConfigEntry DroneItemSpawnChance; internal static ConfigEntry MapHideDroneItems; internal static ConfigEntry UseShopPriceForDroneItems; internal static ConfigEntry SpawnOtherShopItems; internal static ConfigEntry OtherShopItemSpawnChance; internal static ConfigEntry MapHideOtherShopItems; internal static ConfigEntry UseShopPriceForOtherItems; internal static ConfigEntry SpawnHealthPacksFromEnemies; internal static ConfigEntry HealthPackDropChance; internal static ConfigEntry MinItemValue; internal static ConfigEntry MaxItemValue; internal static ConfigEntry MaxItemsPerLevel; internal static Dictionary> ItemAllowList; private static readonly HashSet KnownSpecialTypes = new HashSet { 0, 3, 8 }; public static Plugin Instance { get; private set; } internal static void DebugLog(string message) { if (DebugMode != null && DebugMode.Value) { Logger.LogInfo((object)("[DEBUG] " + message)); } } private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Expected O, but got Unknown //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Expected O, but got Unknown //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin REPO_All_Shop_Items_in_Level is loaded!"); Harmony val = new Harmony("REPO_All_Shop_Items_in_Level"); val.PatchAll(typeof(Plugin)); val.PatchAll(typeof(DespawnPatch)); val.PatchAll(typeof(ValuableDirector_Spawn_Patch)); Logger.LogInfo((object)"Harmony patches applied!"); DebugMode = ((BaseUnityPlugin)this).Config.Bind("0_Debug", "DebugMode", false, "Enable verbose debug logging."); SaveAllOnLevelComplete = ((BaseUnityPlugin)this).Config.Bind("0_Debug", "SaveAllOnLevelComplete", true, "If true, all spawned items still in the level are saved when you complete a level (even if not in the truck). This ensures no item is lost."); SpawnUpgradeItems = ((BaseUnityPlugin)this).Config.Bind("1_UpgradeItems", "SpawnUpgradeItems", true, ""); MapHideUpgradeItems = ((BaseUnityPlugin)this).Config.Bind("1_UpgradeItems", "MapHideUpgradeItems", false, ""); UpgradeItemSpawnChance = ((BaseUnityPlugin)this).Config.Bind("1_UpgradeItems", "UpgradeItemSpawnChance", 2.5f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); UseShopPriceForUpgradeItems = ((BaseUnityPlugin)this).Config.Bind("1_UpgradeItems", "UseShopPriceForItemSelection", true, ""); SpawnDroneItems = ((BaseUnityPlugin)this).Config.Bind("2_DroneItems", "SpawnDroneItems", true, ""); MapHideDroneItems = ((BaseUnityPlugin)this).Config.Bind("2_DroneItems", "MapHideDroneItems", false, ""); DroneItemSpawnChance = ((BaseUnityPlugin)this).Config.Bind("2_DroneItems", "DroneItemsSpawnChance", 0.95f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); UseShopPriceForDroneItems = ((BaseUnityPlugin)this).Config.Bind("2_DroneItems", "UseShopPriceForItemSelection", true, ""); SpawnOtherShopItems = ((BaseUnityPlugin)this).Config.Bind("3_OtherShopItems", "SpawnOtherShopItems", true, ""); MapHideOtherShopItems = ((BaseUnityPlugin)this).Config.Bind("3_OtherShopItems", "MapHideOtherShopItems", false, ""); OtherShopItemSpawnChance = ((BaseUnityPlugin)this).Config.Bind("3_OtherShopItems", "OtherShopItemSpawnChance", 1.5f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); UseShopPriceForOtherItems = ((BaseUnityPlugin)this).Config.Bind("3_OtherShopItems", "UseShopPriceForItemSelection", true, ""); SpawnHealthPacksFromEnemies = ((BaseUnityPlugin)this).Config.Bind("4_HealthPacks", "SpawnHealthPacksFromEnemies", true, ""); HealthPackDropChance = ((BaseUnityPlugin)this).Config.Bind("4_HealthPacks", "HealthPackDropChance", 100f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); MinItemValue = ((BaseUnityPlugin)this).Config.Bind("5_Filters", "MinItemValue", 0f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 999999f), Array.Empty())); MaxItemValue = ((BaseUnityPlugin)this).Config.Bind("5_Filters", "MaxItemValue", 0f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 999999f), Array.Empty())); MaxItemsPerLevel = ((BaseUnityPlugin)this).Config.Bind("5_Filters", "MaxItemsPerLevel", 0, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); ((MonoBehaviour)this).StartCoroutine(PopulateAllowListWhenReady()); } [IteratorStateMachine(typeof(d__28))] private IEnumerator PopulateAllowListWhenReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__28(0) { <>4__this = this }; } private static bool PassesValueFilter(Item item) { float num = (((Object)(object)item.value != (Object)null) ? item.value.valueMin : 0f); if (MinItemValue.Value > 0f && num < MinItemValue.Value) { return false; } if (MaxItemValue.Value > 0f && num > MaxItemValue.Value) { return false; } return true; } private static bool IsItemAllowed(Item item) { if (ItemAllowList == null) { return true; } string name = ((Object)item).name; ConfigEntry value; return !ItemAllowList.TryGetValue(name, out value) || value.Value; } private static List GetCandidates(Func typeFilter) { if (StatsManager.instance?.itemDictionary == null) { return new List(); } return (from i in StatsManager.instance.itemDictionary.Values.Where(typeFilter) where (Object)(object)i.value != (Object)null && i.value.valueMin > 0f select i).Where(PassesValueFilter).Where(IsItemAllowed).ToList(); } private static Item WeightedOrRandom(List list, bool usePrice) { if (!usePrice) { return list[Random.Range(0, list.Count)]; } float num = list.Sum((Item i) => 1f / i.value.valueMin); if (num <= 0f) { return null; } float num2 = Random.Range(0f, num); foreach (Item item in list) { num2 -= 1f / item.value.valueMin; if (num2 <= 0f) { return item; } } return null; } private static bool GetRandomItemOfType(itemType type, 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) item = null; List candidates = GetCandidates((Item i) => i.itemType == type); if (candidates.Count == 0) { return false; } item = candidates[Random.Range(0, candidates.Count)]; return true; } private static bool GetRandomOtherShopItem(out Item item) { item = null; List candidates = GetCandidates((Item i) => !KnownSpecialTypes.Contains((int)i.itemType)); if (candidates.Count == 0) { return false; } item = WeightedOrRandom(candidates, UseShopPriceForOtherItems.Value); return (Object)(object)item != (Object)null; } private static GameObject SpawnItem(Item item, Vector3 position, Quaternion rotation) { //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_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) GameObject val = (SemiFunc.IsMultiplayer() ? PhotonNetwork.Instantiate("Items/" + ((Object)item).name, position, rotation, (byte)0, (object[])null) : Object.Instantiate(((PrefabRef)(object)item.prefab).Prefab, position, rotation)); val.AddComponent(); return val; } private static bool HasValuablePropSwitch(ValuableVolume volume) { return (Object)(object)((Component)volume).GetComponentInParent() != (Object)null; } private static bool ShouldSpawnItem(ValuableVolume volume, out string category) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected I4, but got Unknown category = null; if (HasValuablePropSwitch(volume)) { return false; } switch ((int)volume.VolumeType) { case 0: if (!SpawnUpgradeItems.Value) { return false; } category = "upgrade"; return Random.Range(0f, 100f) <= UpgradeItemSpawnChance.Value; case 1: if (!SpawnDroneItems.Value) { return false; } category = "drone"; return Random.Range(0f, 100f) <= DroneItemSpawnChance.Value; default: if (!SpawnOtherShopItems.Value) { return false; } category = "other"; return Random.Range(0f, 100f) <= OtherShopItemSpawnChance.Value; } } private static bool RandomItemSpawn(ValuableVolume volume) { //IL_006b: 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) if (!ShouldSpawnItem(volume, out var category)) { return false; } if (!((category == "upgrade") ? GetRandomItemOfType((itemType)3, out var item) : ((!(category == "drone")) ? GetRandomOtherShopItem(out item) : GetRandomItemOfType((itemType)0, out item)))) { return false; } SpawnItem(item, ((Component)volume).transform.position, ((Component)volume).transform.rotation); return true; } [HarmonyPatch(typeof(ValuableDirector), "VolumesAndSwitchSetup")] [HarmonyPostfix] public static void ValuableDirector_VolumesAndSwitchSetup_Postfix() { if (!SemiFunc.RunIsLevel()) { return; } List list = (from v in Object.FindObjectsOfType(false) where (Object)(object)((Component)v).gameObject.GetComponent() == (Object)null where !HasValuablePropSwitch(v) select v).ToList(); Logger.LogInfo((object)$"Found {list.Count} volumes (upgrade:{UpgradeItemSpawnChance.Value}%, drone:{DroneItemSpawnChance.Value}%, other:{OtherShopItemSpawnChance.Value}%)"); int value = MaxItemsPerLevel.Value; int num = 0; foreach (ValuableVolume item in list) { if (value > 0 && num >= value) { break; } if (RandomItemSpawn(item)) { num++; } } Logger.LogInfo((object)$"Spawned {num} items total"); } [HarmonyPatch(typeof(Map), "AddCustom")] [HarmonyPostfix] public static void Map_AddCustom_Postfix(MapCustom mapCustom) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected I4, but got Unknown ItemAttributes val = default(ItemAttributes); if (SemiFunc.RunIsLevel() && ((Component)mapCustom).gameObject.TryGetComponent(ref val)) { int num = (int)val.item.itemType; if ((num == 3 && MapHideUpgradeItems.Value) || (num == 0 && MapHideDroneItems.Value) || (!KnownSpecialTypes.Contains(num) && MapHideOtherShopItems.Value)) { ((Component)mapCustom).gameObject.SetActive(false); } } } [HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInHaulList")] [HarmonyPostfix] public static void ExtractionPoint_DestroyAllPhysObjectsInHaulList_Postfix(ExtractionPoint __instance) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } SpawnedItemTracker[] array = Object.FindObjectsOfType(false); int num = 0; SpawnedItemTracker[] array2 = array; foreach (SpawnedItemTracker spawnedItemTracker in array2) { GameObject gameObject = ((Component)spawnedItemTracker).gameObject; bool flag = false; RoomVolumeCheck component = gameObject.GetComponent(); if ((Object)(object)component != (Object)null && component.CurrentRooms.Any((RoomVolume r) => r.Extraction)) { flag = true; DebugLog("Item " + ((Object)gameObject).name + " is inside extraction zone"); } PhysGrabObject component2 = gameObject.GetComponent(); if ((Object)(object)component2 != (Object)null && component2.grabbed) { flag = true; DebugLog("Item " + ((Object)gameObject).name + " is grabbed by a player"); } if (!flag) { continue; } ItemAttributes component3 = gameObject.GetComponent(); if ((Object)(object)component3 == (Object)null || (Object)(object)component3.item == (Object)null) { DebugLog("Item " + ((Object)gameObject).name + " has no ItemAttributes, skipping"); continue; } string name = ((Object)component3.item).name; Logger.LogInfo((object)("Saving extracted item: " + name)); StatsManager.instance.ItemPurchase(name); PhysGrabObject component4 = gameObject.GetComponent(); if (component4 != null) { component4.DestroyPhysGrabObject(); } num++; } Logger.LogInfo((object)$"Saved {num} items from extraction"); } [HarmonyPatch(typeof(RunManager), "ChangeLevel")] [HarmonyPrefix] public static void RunManager_ChangeLevel_Prefix(RunManager __instance, bool _completedLevel, bool _levelFailed, int _changeLevelType) { if (!SemiFunc.IsMasterClientOrSingleplayer() || !_completedLevel || _levelFailed || !SaveAllOnLevelComplete.Value || _changeLevelType == 4) { return; } SpawnedItemTracker[] array = Object.FindObjectsOfType(false); if (array.Length == 0) { return; } Logger.LogInfo((object)$"Level completed. Saving {array.Length} remaining spawned items as purchased (fallback)"); int num = 0; SpawnedItemTracker[] array2 = array; foreach (SpawnedItemTracker spawnedItemTracker in array2) { GameObject gameObject = ((Component)spawnedItemTracker).gameObject; ItemAttributes component = gameObject.GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.item == (Object)null)) { string name = ((Object)component.item).name; DebugLog("Fallback save: " + name); StatsManager.instance.ItemPurchase(name); num++; } } Logger.LogInfo((object)$"Fallback saved {num} items"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "REPO_All_Shop_Items_in_Level"; public const string PLUGIN_NAME = "ALL Shop Items spawn in Level"; public const string PLUGIN_VERSION = "1.7.23"; } }