using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EnemyCompatibilityFixes")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0")] [assembly: AssemblyProduct("EnemyCompatibilityFixes")] [assembly: AssemblyTitle("EnemyCompatibilityFixes")] [assembly: AssemblyVersion("1.2.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnemyCompatibilityFixes { [BepInPlugin("enemycompatibilityfixes.plugin", "Enemy Compatibility Fixes", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "enemycompatibilityfixes.plugin"; public const string PluginName = "Enemy Compatibility Fixes"; public const string PluginVersion = "1.2.0"; private Harmony _harmony; private ConfigEntry _fixMinecraftSpider; private ConfigEntry _guardScp999Targeting; private ConfigEntry _fixModelReplacementSlots; private ConfigEntry _fixModDataRegistration; private ConfigEntry _fixLethalCasinoMenu; private ConfigEntry _fixUtilitySlotDestruction; private ConfigEntry _fixOccludedAudio; private ConfigEntry _fixPermanentMoonsDisconnect; private ConfigEntry _enableDaySpeed; private ConfigEntry _daySpeedMultiplier; private ConfigEntry _enableDifficultyScrap; private ConfigEntry _scrapD; private ConfigEntry _scrapC; private ConfigEntry _scrapB; private ConfigEntry _scrapA; private ConfigEntry _scrapS; private ConfigEntry _scrapSS; private ConfigEntry _scrapUnknown; private ConfigEntry _showMoonPrices; private ConfigEntry _compensateEnemySchedule; private ConfigEntry _enemyScheduleMultiplier; private ConfigEntry _minimumInsideEnemies; private ConfigEntry _minimumOutsideEnemies; private ConfigEntry _showShipScanNode; private ConfigEntry _showMainEntranceScanNode; private ConfigEntry _navigationScanRange; private ConfigEntry _compressInteriorWeights; private ConfigEntry _interiorWeightExponent; private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown BindFixSettings(); BindGameplaySettings(); _harmony = new Harmony("enemycompatibilityfixes.plugin"); if (_fixMinecraftSpider.Value) { PatchMinecraftSpider(); } if (_guardScp999Targeting.Value) { PatchScp999Targeting(); } if (_fixModelReplacementSlots.Value) { PatchModelReplacementSlots(); } if (_fixModDataRegistration.Value) { PatchModDataRegistration(); } if (_fixLethalCasinoMenu.Value) { PatchLethalCasinoMenu(); } if (_fixUtilitySlotDestruction.Value) { PatchUtilitySlotDestruction(); } if (_fixOccludedAudio.Value) { PatchOccludedAudio(); } if (_fixPermanentMoonsDisconnect.Value) { PatchPermanentMoonsDisconnect(); } PatchGameplaySettings(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Enemy Compatibility Fixes 1.2.0 loaded."); } private void BindFixSettings() { _fixMinecraftSpider = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Fix Minecraft Spider state", true, "Prevents MinecraftSpiderMod from accessing invalid state after level transitions, unusual spawning, or enemy cleanup."); _guardScp999Targeting = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Guard SCP-999 enemy targeting", true, "Stops SCP-999 enemy targeting from flooding the log when another enemy has incomplete targeting data."); _fixModelReplacementSlots = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Fix ModelReplacement item slots", true, "Prevents ModelReplacementAPI from reading outside the inventory array when a tool or reserved slot is selected."); _fixModDataRegistration = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Fix LethalModDataLib registration", true, "Skips unloaded plugin instances while LethalModDataLib scans mod data attributes."); _fixLethalCasinoMenu = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Fix LethalCasino menu check", true, "Skips an obsolete LC_API warning check that calls a menu method removed from the current game."); _fixUtilitySlotDestruction = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Fix utility slot item destruction", true, "Uses the correct HUD icon when an item in the game's utility-only slot is destroyed."); _fixOccludedAudio = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Guard broken occluded audio", true, "Stops invalid OccludeAudio components from flooding the log every frame on broken custom scenes."); _fixPermanentMoonsDisconnect = ((BaseUnityPlugin)this).Config.Bind("Fixes", "Fix Permanent Moons disconnect", true, "Prevents Permanent Moons from accessing the messaging manager after networking has already shut down."); } private void BindGameplaySettings() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Expected O, but got Unknown //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Expected O, but got Unknown _enableDaySpeed = ((BaseUnityPlugin)this).Config.Bind("Time", "Enable day speed multiplier", true, "Enables the global day speed setting below. This stacks with each moon's DaySpeedMultiplier."); _daySpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind("Time", "Day speed multiplier", 1f, new ConfigDescription("How quickly time passes. 0 pauses the day, 0.5 makes it twice as long, 1 is normal, and 2 makes it twice as fast.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); _enableDifficultyScrap = ((BaseUnityPlugin)this).Config.Bind("Scrap by moon difficulty", "Enable scrap count multipliers", true, "Changes the number of spawned scrap items according to the moon's displayed risk level. The host controls the result."); _scrapD = BindPercent("D or easier percent", 150, "Scrap count on D, safe, and similarly easy moons."); _scrapC = BindPercent("C percent", 135, "Scrap count on C and C+ moons."); _scrapB = BindPercent("B percent", 120, "Scrap count on B and B+ moons."); _scrapA = BindPercent("A percent", 110, "Scrap count on A and A+ moons."); _scrapS = BindPercent("S percent", 100, "Scrap count on S and S+ moons."); _scrapSS = BindPercent("SS or harder percent", 100, "Scrap count on SS, SSS, and harder moons."); _scrapUnknown = BindPercent("Unknown difficulty percent", 100, "Scrap count when a custom moon uses an unrecognized risk label."); _showMoonPrices = ((BaseUnityPlugin)this).Config.Bind("Terminal", "Show current moon prices", true, "Adds each moon's current route price after its weather in the moons catalogue."); _compensateEnemySchedule = ((BaseUnityPlugin)this).Config.Bind("Enemy spawning", "Compensate for slower days", true, "Moves scheduled indoor enemy spawns earlier when the day speed multiplier is below 1. The host controls spawning."); _enemyScheduleMultiplier = ((BaseUnityPlugin)this).Config.Bind("Enemy spawning", "Enemy schedule multiplier", 0f, new ConfigDescription("0 automatically follows the day speed multiplier. Values below 1 make scheduled enemies appear earlier; 1 leaves timing unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty())); _minimumInsideEnemies = ((BaseUnityPlugin)this).Config.Bind("Enemy spawning", "Minimum inside enemies per batch", 1, new ConfigDescription("Minimum number considered for each indoor spawn batch. 0 keeps the game's normal minimum.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 20), Array.Empty())); _minimumOutsideEnemies = ((BaseUnityPlugin)this).Config.Bind("Enemy spawning", "Minimum outside enemies per batch", 1, new ConfigDescription("Minimum number considered for each outside spawn batch. 0 keeps the game's normal minimum.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 20), Array.Empty())); _showShipScanNode = ((BaseUnityPlugin)this).Config.Bind("Outside scanner", "Always show ship", true, "Shows the ship as a navigation marker whenever the scanner is used outside."); _showMainEntranceScanNode = ((BaseUnityPlugin)this).Config.Bind("Outside scanner", "Always show main entrance", true, "Shows the main entrance as a navigation marker whenever the scanner is used outside."); _navigationScanRange = ((BaseUnityPlugin)this).Config.Bind("Outside scanner", "Navigation marker range", 10000, new ConfigDescription("Maximum range of the ship and main entrance scan markers.", (AcceptableValueBase)(object)new AcceptableValueRange(50, 50000), Array.Empty())); _compressInteriorWeights = ((BaseUnityPlugin)this).Config.Bind("Interior variety", "Compress interior weight differences", true, "Reduces extreme rarity differences among interiors that are actually valid for the selected moon."); _interiorWeightExponent = ((BaseUnityPlugin)this).Config.Bind("Interior variety", "Weight exponent percent", 50, new ConfigDescription("100 keeps original weights, 50 uses their square root, and 0 makes all valid interiors equally likely.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); } private ConfigEntry BindPercent(string key, int defaultValue, string description) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind("Scrap by moon difficulty", key, defaultValue, new ConfigDescription(description + " 100 means unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 500), Array.Empty())); } private void PatchMinecraftSpider() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown Type type = FindType("MinecraftSpiderMod.Patches.SandSpiderAIPatch"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"MinecraftSpiderMod was not found; its compatibility fix was skipped."); return; } SpiderStateGuard.Initialize(type, ((BaseUnityPlugin)this).Logger); HarmonyMethod val = new HarmonyMethod(typeof(SpiderStateGuard), "EnsureStatePrefix", (Type[])null); val.priority = 800; val.before = new string[1] { "SkunkWerx.MinecraftSpiderMod" }; HarmonyMethod val2 = val; string[] array = new string[2] { "Update", "MoveLegsProcedurally" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(typeof(SandSpiderAI), text, (Type[])null, (Type[])null); if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } MethodInfo methodInfo2 = AccessTools.Method(typeof(SandSpiderAI), "KillEnemy", (Type[])null, (Type[])null); if (methodInfo2 != null) { HarmonyMethod val3 = new HarmonyMethod(typeof(SpiderStateGuard), "KillEnemyFinalizer", (Type[])null); _harmony.Patch((MethodBase)methodInfo2, val2, (HarmonyMethod)null, (HarmonyMethod)null, val3, (HarmonyMethod)null); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"MinecraftSpiderMod state guard enabled."); } private void PatchScp999Targeting() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown Type type = FindType("SnowyLib.EnemyAIExtensions"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"SnowyLib was not found; the SCP-999 targeting guard was skipped."); return; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo method) => method.Name == "TargetClosestEnemy" && method.ReturnType == typeof(bool)); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"SnowyLib.TargetClosestEnemy was not found; the SCP-999 targeting guard could not be applied."); return; } Scp999TargetingGuard.SetLogger(((BaseUnityPlugin)this).Logger); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Scp999TargetingGuard), "Finalizer", (Type[])null), (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"SCP-999 targeting exception guard enabled."); } private void PatchModelReplacementSlots() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown Type type = FindType("ModelReplacement.BodyReplacementBase"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "UpdateItemTransform", (Type[])null, (Type[])null)); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"ModelReplacementAPI was not found; its item-slot guard was skipped."); return; } ModelReplacementSlotGuard.Initialize(type, ((BaseUnityPlugin)this).Logger); _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ModelReplacementSlotGuard), "Prefix", (Type[])null) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"ModelReplacementAPI item-slot guard enabled."); } private void PatchModDataRegistration() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown Type type = FindType("LethalModDataLib.Features.ModDataAttributeCollector"); MethodInfo methodInfo = type?.GetMethod("RegisterModDataAttributes", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); MethodInfo methodInfo2 = type?.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo method) => method.Name == "RegisterModDataAttributes" && method.GetParameters().Length == 4); if (methodInfo == null || methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalModDataLib was not found; its registration guard was skipped."); return; } ModDataRegistrationGuard.Initialize(methodInfo2, ((BaseUnityPlugin)this).Logger); _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ModDataRegistrationGuard), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalModDataLib registration guard enabled."); } private void PatchLethalCasinoMenu() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Type type = FindType("LethalCasino.Patches.MenuManagerPatch"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "StartPatch", (Type[])null, (Type[])null)); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalCasino was not found; its obsolete menu check guard was skipped."); return; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(LethalCasinoMenuGuard), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalCasino obsolete menu check disabled."); } private void PatchUtilitySlotDestruction() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(PlayerControllerB), "DestroyItemInSlot", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"PlayerControllerB.DestroyItemInSlot was not found; its utility-slot fix was skipped."); return; } UtilitySlotDestructionPatch.SetLogger(((BaseUnityPlugin)this).Logger); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(UtilitySlotDestructionPatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Utility-only slot destruction fix enabled."); } private void PatchGameplaySettings() { //IL_00f1: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_0127: Expected O, but got Unknown //IL_0127: Expected O, but got Unknown //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: 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) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_019c: Expected O, but got Unknown //IL_019c: Expected O, but got Unknown //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Expected O, but got Unknown //IL_0297: Expected O, but got Unknown //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Expected O, but got Unknown TimeSpeedPatch.Initialize(_enableDaySpeed, _daySpeedMultiplier); ScrapAmountPatch.Initialize(_enableDifficultyScrap, _scrapD, _scrapC, _scrapB, _scrapA, _scrapS, _scrapSS, _scrapUnknown, ((BaseUnityPlugin)this).Logger); EnemySpawnTimingPatch.Initialize(_compensateEnemySchedule, _enemyScheduleMultiplier, _enableDaySpeed, _daySpeedMultiplier, _minimumInsideEnemies, _minimumOutsideEnemies, ((BaseUnityPlugin)this).Logger); TerminalMoonPricePatch.Initialize(_showMoonPrices, ((BaseUnityPlugin)this).Logger); NavigationScanPatch.Initialize(_showShipScanNode, _showMainEntranceScanNode, _navigationScanRange); InteriorWeightPatch.Initialize(_compressInteriorWeights, _interiorWeightExponent, ((BaseUnityPlugin)this).Logger); MethodInfo methodInfo = AccessTools.Method(typeof(TimeOfDay), "MoveGlobalTime", (Type[])null, (Type[])null); if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(TimeSpeedPatch), "Prefix", (Type[])null), new HarmonyMethod(typeof(TimeSpeedPatch), "Restore", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(TimeSpeedPatch), "Finalizer", (Type[])null), (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.Method(typeof(RoundManager), "SpawnScrapInLevel", (Type[])null, (Type[])null); if (methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(ScrapAmountPatch), "Prefix", (Type[])null) { priority = 0 }, new HarmonyMethod(typeof(ScrapAmountPatch), "Restore", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ScrapAmountPatch), "Finalizer", (Type[])null), (HarmonyMethod)null); } MethodInfo methodInfo3 = AccessTools.Method(typeof(RoundManager), "PlotOutEnemiesForNextHour", (Type[])null, (Type[])null); if (methodInfo3 != null) { _harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(EnemySpawnTimingPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo4 = AccessTools.Method(typeof(RoundManager), "BeginEnemySpawning", (Type[])null, (Type[])null); if (methodInfo4 != null) { _harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(EnemySpawnTimingPatch), "BeginPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo5 = AccessTools.Method(typeof(Terminal), "TextPostProcess", (Type[])null, (Type[])null); if (methodInfo5 != null) { _harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(TerminalMoonPricePatch), "Prefix", (Type[])null) { priority = 800 }, new HarmonyMethod(typeof(TerminalMoonPricePatch), "Postfix", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo6 = AccessTools.Method(typeof(HUDManager), "AssignNewNodes", (Type[])null, (Type[])null); if (methodInfo6 != null) { _harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(typeof(NavigationScanPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } PatchInteriorWeights(); } private void PatchOccludedAudio() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(OccludeAudio), "Update", (Type[])null, (Type[])null); if (!(methodInfo == null)) { OccludedAudioGuard.SetLogger(((BaseUnityPlugin)this).Logger); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(OccludedAudioGuard), "Finalizer", (Type[])null), (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"OccludeAudio exception guard enabled."); } } private void PatchPermanentMoonsDisconnect() { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown Type type = FindType("Plugin"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "UnregisterMessages", (Type[])null, (Type[])null)); if (methodInfo == null || type.Assembly.GetName().Name != "PermanentMoons") { methodInfo = (from assembly in AppDomain.CurrentDomain.GetAssemblies() where assembly.GetName().Name == "PermanentMoons" select assembly.GetType("Plugin", throwOnError: false) into type2 where type2 != null select AccessTools.Method(type2, "UnregisterMessages", (Type[])null, (Type[])null)).FirstOrDefault((MethodInfo method) => method != null); } if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Permanent Moons was not found; its disconnect guard was skipped."); return; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PermanentMoonsDisconnectGuard), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Permanent Moons disconnect guard enabled."); } private void PatchInteriorWeights() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Type type = FindType("LethalLevelLoader.DungeonManager"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetValidExtendedDungeonFlows", (Type[])null, (Type[])null)); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalLevelLoader was not found; interior weight compression was skipped."); return; } InteriorWeightPatch.InitializeResultType(methodInfo.ReturnType); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(InteriorWeightPatch), "Postfix", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Interior weight compression support enabled."); } private static Type FindType(string fullName) { return (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType(fullName, throwOnError: false)).FirstOrDefault((Type type) => type != null); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class SpiderStateGuard { private static FieldInfo _timerDictionaryField; private static ManualLogSource _logger; private static int _repairNoticeWritten; private static int _killNoticeWritten; internal static void Initialize(Type spiderPatchType, ManualLogSource logger) { _timerDictionaryField = AccessTools.Field(spiderPatchType, "_timeSinceMovingLegs"); _logger = logger; } public static void EnsureStatePrefix(SandSpiderAI __instance) { if ((Object)(object)__instance == (Object)null || _timerDictionaryField == null) { return; } try { IDictionary dictionary = _timerDictionaryField.GetValue(null) as IDictionary; if (dictionary == null) { dictionary = Activator.CreateInstance(_timerDictionaryField.FieldType) as IDictionary; _timerDictionaryField.SetValue(null, dictionary); } if (dictionary == null || dictionary.Contains(__instance)) { return; } dictionary.Add(__instance, Random.Range(0.1f, 0.9f)); if (Interlocked.Exchange(ref _repairNoticeWritten, 1) == 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)"Repaired missing MinecraftSpiderMod leg state."); } } } catch (Exception ex) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Could not initialize MinecraftSpiderMod state: " + ex.Message)); } } } public static Exception KillEnemyFinalizer(Exception __exception) { if (__exception is NullReferenceException) { if (Interlocked.Exchange(ref _killNoticeWritten, 1) == 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)"Ignored invalid MinecraftSpiderMod cleanup data while a spider was being removed."); } } return null; } return __exception; } } internal static class Scp999TargetingGuard { private static ManualLogSource _logger; private static int _noticeWritten; internal static void SetLogger(ManualLogSource logger) { _logger = logger; } public static Exception Finalizer(Exception __exception, ref bool __result) { if (__exception is NullReferenceException) { __result = false; if (Interlocked.Exchange(ref _noticeWritten, 1) == 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)"Ignored invalid enemy data while SCP-999 was selecting a target."); } } return null; } return __exception; } } internal static class ModelReplacementSlotGuard { private static FieldInfo _heldItemField; private static MethodInfo _controllerGetter; private static ManualLogSource _logger; private static int _noticeWritten; internal static void Initialize(Type bodyType, ManualLogSource logger) { _heldItemField = AccessTools.Field(bodyType, "heldItem"); _controllerGetter = AccessTools.PropertyGetter(bodyType, "controller"); _logger = logger; } public static bool Prefix(object __instance) { if (__instance == null || _heldItemField == null || _controllerGetter == null) { return true; } try { object? value = _heldItemField.GetValue(__instance); GrabbableObject val = (GrabbableObject)((value is GrabbableObject) ? value : null); if ((Object)(object)val == (Object)null || val is BeltBagItem) { return true; } object? obj = _controllerGetter.Invoke(__instance, null); object? obj2 = ((obj is PlayerControllerB) ? obj : null); int num = ((PlayerControllerB)(obj2?)).currentItemSlot ?? (-1); int valueOrDefault = (((PlayerControllerB)(obj2?)).ItemSlots?.Length).GetValueOrDefault(); if (num >= 0 && num < valueOrDefault) { return true; } _heldItemField.SetValue(__instance, null); if (Interlocked.Exchange(ref _noticeWritten, 1) == 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)$"Prevented ModelReplacementAPI item-slot overflow (slot {num}, inventory size {valueOrDefault})."); } } return false; } catch (Exception ex) { if (Interlocked.Exchange(ref _noticeWritten, 1) == 0) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Could not validate a ModelReplacementAPI item slot: " + ex.Message)); } } return true; } } } internal static class ModDataRegistrationGuard { private static MethodInfo _registerOne; private static ManualLogSource _logger; internal static void Initialize(MethodInfo registerOne, ManualLogSource logger) { _registerOne = registerOne; _logger = logger; } public static bool Prefix() { if (_registerOne == null) { return true; } int num = 0; foreach (PluginInfo value in Chainloader.PluginInfos.Values) { BaseUnityPlugin val = ((value != null) ? value.Instance : null); if ((Object)(object)val == (Object)null) { num++; continue; } IEnumerable loadableTypes; try { loadableTypes = GetLoadableTypes(((object)val).GetType().Assembly); } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { BepInPlugin metadata = value.Metadata; logger.LogWarning((object)("Could not inspect " + (((metadata != null) ? metadata.GUID : null) ?? "an unknown plugin") + " for mod data: " + ex.Message)); } continue; } foreach (Type item in loadableTypes) { try { _registerOne.Invoke(null, new object[4] { value.Metadata.GUID, item, null, null }); } catch (TargetInvocationException ex2) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Could not register mod data from " + item.FullName + ": " + (ex2.InnerException ?? ex2).Message)); } } catch (Exception ex3) { ManualLogSource logger3 = _logger; if (logger3 != null) { logger3.LogWarning((object)("Could not register mod data from " + item.FullName + ": " + ex3.Message)); } } } } if (num > 0) { ManualLogSource logger4 = _logger; if (logger4 != null) { logger4.LogInfo((object)$"Skipped {num} unloaded plugin instance(s) during LethalModDataLib registration."); } } return false; } private static IEnumerable GetLoadableTypes(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type type) => type != null); } } } internal static class LethalCasinoMenuGuard { public static bool Prefix() { return false; } } internal static class UtilitySlotDestructionPatch { private static ManualLogSource _logger; internal static void SetLogger(ManualLogSource logger) { _logger = logger; } public static IEnumerable Transpiler(IEnumerable instructions) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown List list = instructions.ToList(); MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(HUDManager), "Instance"); FieldInfo fieldInfo = AccessTools.Field(typeof(HUDManager), "itemSlotIcons"); MethodInfo methodInfo2 = AccessTools.PropertySetter(typeof(Behaviour), "enabled"); MethodInfo methodInfo3 = AccessTools.Method(typeof(UtilitySlotDestructionPatch), "DisableCorrectSlotIcon", (Type[])null, (Type[])null); for (int i = 0; i <= list.Count - 6; i++) { if (CodeInstructionExtensions.Calls(list[i], methodInfo) && CodeInstructionExtensions.LoadsField(list[i + 1], fieldInfo, false) && !(list[i + 2].opcode != OpCodes.Ldarg_1) && !(list[i + 3].opcode != OpCodes.Ldelem_Ref) && !(list[i + 4].opcode != OpCodes.Ldc_I4_0) && CodeInstructionExtensions.Calls(list[i + 5], methodInfo2)) { CodeInstruction item = new CodeInstruction(OpCodes.Call, (object)methodInfo3); list.RemoveRange(i, 6); list.Insert(i, new CodeInstruction(OpCodes.Ldarg_1, (object)null)); list.Insert(i + 1, item); ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)"Patched DestroyItemInSlot for the utility-only HUD slot."); } return list; } } ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)"Could not locate the utility-slot HUD sequence in DestroyItemInSlot; original code was left unchanged."); } return list; } public static void DisableCorrectSlotIcon(int itemSlot) { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return; } if (itemSlot == 50) { if ((Object)(object)instance.itemOnlySlotIcon != (Object)null) { ((Behaviour)instance.itemOnlySlotIcon).enabled = false; } } else if (instance.itemSlotIcons != null && itemSlot >= 0 && itemSlot < instance.itemSlotIcons.Length && (Object)(object)instance.itemSlotIcons[itemSlot] != (Object)null) { ((Behaviour)instance.itemSlotIcons[itemSlot]).enabled = false; } } } internal static class TimeSpeedPatch { private static ConfigEntry _enabled; private static ConfigEntry _multiplier; internal static void Initialize(ConfigEntry enabled, ConfigEntry multiplier) { _enabled = enabled; _multiplier = multiplier; } public static void Prefix(TimeOfDay __instance, out float __state) { __state = __instance.globalTimeSpeedMultiplier; if (_enabled.Value) { __instance.globalTimeSpeedMultiplier = __state * _multiplier.Value; } } public static void Restore(TimeOfDay __instance, float __state) { __instance.globalTimeSpeedMultiplier = __state; } public static Exception Finalizer(TimeOfDay __instance, float __state, Exception __exception) { __instance.globalTimeSpeedMultiplier = __state; return __exception; } } internal static class ScrapAmountPatch { private static ConfigEntry _enabled; private static ConfigEntry _d; private static ConfigEntry _c; private static ConfigEntry _b; private static ConfigEntry _a; private static ConfigEntry _s; private static ConfigEntry _ss; private static ConfigEntry _unknown; private static ManualLogSource _logger; internal static void Initialize(ConfigEntry enabled, ConfigEntry d, ConfigEntry c, ConfigEntry b, ConfigEntry a, ConfigEntry s, ConfigEntry ss, ConfigEntry unknown, ManualLogSource logger) { _enabled = enabled; _d = d; _c = c; _b = b; _a = a; _s = s; _ss = ss; _unknown = unknown; _logger = logger; } public static void Prefix(RoundManager __instance, out float __state) { __state = __instance.scrapAmountMultiplier; if (_enabled.Value && !((Object)(object)__instance.currentLevel == (Object)null)) { string text = (__instance.currentLevel.riskLevel ?? string.Empty).Trim().ToUpperInvariant(); int percent = GetPercent(text); __instance.scrapAmountMultiplier = __state * (float)percent / 100f; ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)$"Scrap count multiplier for {__instance.currentLevel.PlanetName} (risk {text}): {percent}%."); } } } public static void Restore(RoundManager __instance, float __state) { __instance.scrapAmountMultiplier = __state; } public static Exception Finalizer(RoundManager __instance, float __state, Exception __exception) { __instance.scrapAmountMultiplier = __state; return __exception; } private static int GetPercent(string risk) { if (risk.StartsWith("SS", StringComparison.Ordinal)) { return _ss.Value; } if (risk.StartsWith("S", StringComparison.Ordinal)) { return _s.Value; } if (risk.StartsWith("A", StringComparison.Ordinal)) { return _a.Value; } if (risk.StartsWith("B", StringComparison.Ordinal)) { return _b.Value; } if (risk.StartsWith("C", StringComparison.Ordinal)) { return _c.Value; } if (risk.StartsWith("D", StringComparison.Ordinal) || risk.Contains("SAFE") || risk.Contains("EASY")) { return _d.Value; } return _unknown.Value; } } internal static class OccludedAudioGuard { private static ManualLogSource _logger; private static int _noticeWritten; internal static void SetLogger(ManualLogSource logger) { _logger = logger; } public static Exception Finalizer(OccludeAudio __instance, Exception __exception) { if (!(__exception is NullReferenceException)) { return __exception; } if ((Object)(object)__instance != (Object)null) { ((Behaviour)__instance).enabled = false; } if (Interlocked.Exchange(ref _noticeWritten, 1) == 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)"Disabled a broken OccludeAudio component that was throwing every frame."); } } return null; } } internal static class PermanentMoonsDisconnectGuard { public static bool Prefix() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null) { return singleton.CustomMessagingManager != null; } return false; } } internal static class EnemySpawnTimingPatch { private static ConfigEntry _enabled; private static ConfigEntry _scheduleMultiplier; private static ConfigEntry _daySpeedEnabled; private static ConfigEntry _daySpeedMultiplier; private static ConfigEntry _minimumInside; private static ConfigEntry _minimumOutside; private static ManualLogSource _logger; private static int _lastLoggedDay = int.MinValue; internal static void Initialize(ConfigEntry enabled, ConfigEntry scheduleMultiplier, ConfigEntry daySpeedEnabled, ConfigEntry daySpeedMultiplier, ConfigEntry minimumInside, ConfigEntry minimumOutside, ManualLogSource logger) { _enabled = enabled; _scheduleMultiplier = scheduleMultiplier; _daySpeedEnabled = daySpeedEnabled; _daySpeedMultiplier = daySpeedMultiplier; _minimumInside = minimumInside; _minimumOutside = minimumOutside; _logger = logger; } public static void BeginPrefix(RoundManager __instance) { if (_enabled.Value && !((Object)(object)__instance == (Object)null)) { __instance.minEnemiesToSpawn = Math.Max(__instance.minEnemiesToSpawn, _minimumInside.Value); __instance.minOutsideEnemiesToSpawn = Math.Max(__instance.minOutsideEnemiesToSpawn, _minimumOutside.Value); } } public static void Postfix(RoundManager __instance) { if (!_enabled.Value || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsServer || (Object)(object)__instance.timeScript == (Object)null) { return; } float num = _scheduleMultiplier.Value; if (num <= 0f) { num = (_daySpeedEnabled.Value ? _daySpeedMultiplier.Value : 1f); } num = Mathf.Clamp(num, 0.05f, 5f); if (num >= 0.999f) { return; } float currentDayTime = __instance.timeScript.currentDayTime; for (int i = 0; i < __instance.enemySpawnTimes.Count; i++) { int num2 = __instance.enemySpawnTimes[i]; int value = Mathf.CeilToInt(currentDayTime + Math.Max(1f, (float)num2 - currentDayTime) * num); __instance.enemySpawnTimes[i] = value; } __instance.enemySpawnTimes.Sort(); if (__instance.allEnemyVents != null) { EnemyVent[] allEnemyVents = __instance.allEnemyVents; foreach (EnemyVent val in allEnemyVents) { if (!((Object)(object)val == (Object)null) && val.occupied && !(val.spawnTime <= currentDayTime)) { val.spawnTime = currentDayTime + Math.Max(1f, val.spawnTime - currentDayTime) * num; } } } int num3 = StartOfRound.Instance?.gameStats?.daysSpent ?? (-1); if (_lastLoggedDay != num3) { _lastLoggedDay = num3; ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)$"Enemy schedule compensation active at {num:0.##}x with minimum batches inside/outside {_minimumInside.Value}/{_minimumOutside.Value}."); } } } } internal static class TerminalMoonPricePatch { private const string MarkerPrefix = "[ecfMoonPrice:"; private static ConfigEntry _enabled; private static ManualLogSource _logger; private static readonly Regex MarkerRegex = new Regex("\\[ecfMoonPrice:(\\d+)\\]", RegexOptions.Compiled); internal static void Initialize(ConfigEntry enabled, ManualLogSource logger) { _enabled = enabled; _logger = logger; } public static void Prefix(ref string modifiedDisplayText) { if (_enabled.Value && !string.IsNullOrEmpty(modifiedDisplayText) && modifiedDisplayText.Contains("[planetTime]")) { int index = 0; modifiedDisplayText = Regex.Replace(modifiedDisplayText, Regex.Escape("[planetTime]"), (Match _) => "[planetTime][ecfMoonPrice:" + index++ + "]"); } } public static void Postfix(Terminal __instance, ref string __result) { if (!_enabled.Value || string.IsNullOrEmpty(__result) || !__result.Contains("[ecfMoonPrice:")) { return; } try { __result = MarkerRegex.Replace(__result, delegate(Match match) { if (!int.TryParse(match.Groups[1].Value, out var result) || __instance?.moonsCatalogueList == null || result < 0 || result >= __instance.moonsCatalogueList.Length) { return string.Empty; } int currentRoutePrice = GetCurrentRoutePrice(__instance.moonsCatalogueList[result]); return $" // Price: ${Math.Max(0, currentRoutePrice)}"; }); } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("Could not add moon prices to the terminal: " + ex.Message)); } __result = MarkerRegex.Replace(__result, string.Empty); } } private static int GetCurrentRoutePrice(SelectableLevel level) { if ((Object)(object)level == (Object)null) { return 0; } try { Type type = (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType("LethalLevelLoader.PatchedContent", throwOnError: false)).FirstOrDefault((Type type3) => type3 != null); if (((type == null) ? null : AccessTools.Property(type, "ExtendedLevels"))?.GetValue(null, null) is IEnumerable enumerable) { foreach (object item in enumerable) { Type type2 = item.GetType(); object? obj = AccessTools.Property(type2, "SelectableLevel")?.GetValue(item, null); if (!((Object)((obj is SelectableLevel) ? obj : null) != (Object)(object)level)) { object obj2 = AccessTools.Property(type2, "RoutePrice")?.GetValue(item, null) ?? AccessTools.Field(type2, "routePrice")?.GetValue(item); if (obj2 is int) { return (int)obj2; } } } } } catch { } Terminal val = Object.FindObjectOfType(); if (val?.terminalNodes?.allKeywords != null) { TerminalKeyword[] allKeywords = val.terminalNodes.allKeywords; foreach (TerminalKeyword val2 in allKeywords) { if (val2?.compatibleNouns == null) { continue; } CompatibleNoun[] compatibleNouns = val2.compatibleNouns; for (int num2 = 0; num2 < compatibleNouns.Length; num2++) { TerminalNode val3 = compatibleNouns[num2]?.result; if ((Object)(object)val3 != (Object)null && val3.displayPlanetInfo == level.levelID && val3.itemCost >= 0) { return val3.itemCost; } } } } return 0; } } internal static class NavigationScanPatch { private static ConfigEntry _shipEnabled; private static ConfigEntry _entranceEnabled; private static ConfigEntry _range; private static ScanNodeProperties _shipNode; private static ScanNodeProperties _entranceNode; private static MethodInfo _attemptScanNode; internal static void Initialize(ConfigEntry shipEnabled, ConfigEntry entranceEnabled, ConfigEntry range) { _shipEnabled = shipEnabled; _entranceEnabled = entranceEnabled; _range = range; _attemptScanNode = AccessTools.Method(typeof(HUDManager), "AttemptScanNode", (Type[])null, (Type[])null); } public static void Postfix(HUDManager __instance, PlayerControllerB playerScript) { if ((Object)(object)__instance == (Object)null || (Object)(object)playerScript == (Object)null || playerScript.isInsideFactory || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.inShipPhase) { return; } if (_shipEnabled.Value) { Transform anchor = (((Object)(object)StartOfRound.Instance.shipBounds != (Object)null) ? ((Component)StartOfRound.Instance.shipBounds).transform : StartOfRound.Instance.elevatorTransform); _shipNode = GetOrCreateNode(_shipNode, anchor, "ECF Ship Scan Node", "SHIP", "Navigation"); if ((Object)(object)_shipNode != (Object)null) { _attemptScanNode?.Invoke(__instance, new object[3] { _shipNode, -1, playerScript }); } } if (_entranceEnabled.Value) { EntranceTeleport val = ((IEnumerable)Object.FindObjectsOfType()).FirstOrDefault((Func)((EntranceTeleport item) => (Object)(object)item != (Object)null && item.entranceId == 0 && item.isEntranceToBuilding)); Transform anchor2 = (((Object)(object)val?.entrancePoint != (Object)null) ? val.entrancePoint : ((val != null) ? ((Component)val).transform : null)); _entranceNode = GetOrCreateNode(_entranceNode, anchor2, "ECF Main Entrance Scan Node", "MAIN ENTRANCE", "Navigation"); if ((Object)(object)_entranceNode != (Object)null) { _attemptScanNode?.Invoke(__instance, new object[3] { _entranceNode, -1, playerScript }); } } } private static ScanNodeProperties GetOrCreateNode(ScanNodeProperties existing, Transform anchor, string objectName, string header, string subText) { //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_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)anchor == (Object)null) { return null; } if ((Object)(object)existing == (Object)null) { GameObject val = new GameObject(objectName); val.transform.SetParent(anchor, false); existing = val.AddComponent(); } else if ((Object)(object)((Component)existing).transform.parent != (Object)(object)anchor) { ((Component)existing).transform.SetParent(anchor, false); } ((Component)existing).transform.localPosition = Vector3.zero; existing.maxRange = _range.Value; existing.minRange = -1; existing.requiresLineOfSight = false; existing.headerText = header; existing.subText = subText; existing.nodeType = 1; return existing; } } internal static class InteriorWeightPatch { private static ConfigEntry _enabled; private static ConfigEntry _exponentPercent; private static FieldInfo _rarityField; private static ManualLogSource _logger; private static int _noticeWritten; internal static void Initialize(ConfigEntry enabled, ConfigEntry exponentPercent, ManualLogSource logger) { _enabled = enabled; _exponentPercent = exponentPercent; _logger = logger; } internal static void InitializeResultType(Type resultType) { Type type = (resultType.IsGenericType ? resultType.GetGenericArguments().FirstOrDefault() : null); _rarityField = ((type == null) ? null : AccessTools.Field(type, "rarity")); } public static void Postfix(object __result) { if (!_enabled.Value || _rarityField == null || !(__result is IEnumerable enumerable)) { return; } float num = (float)_exponentPercent.Value / 100f; int num2 = 0; foreach (object item in enumerable) { if (item == null) { continue; } int num3 = (int)_rarityField.GetValue(item); if (num3 > 0) { int num4 = ((num <= 0f) ? 1 : Math.Max(1, Mathf.RoundToInt(Mathf.Pow((float)num3, num)))); if (num4 != num3) { _rarityField.SetValue(item, num4); num2++; } } } if (num2 > 0 && Interlocked.Exchange(ref _noticeWritten, 1) == 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)$"Compressed {num2} valid interior selection weights using exponent {_exponentPercent.Value}%."); } } } } }