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 LethalLevelLoaderUpdated v1.6.0
BepInEx/plugins/LethalLevelLoader.dll
Decompiled 4 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dawn; using DunGen; using DunGen.Graph; using GameNetcodeStuff; using HarmonyLib; using LethalLevelLoader; using LethalLevelLoader.AssetBundles; using LethalLevelLoader.Compatibility; using LethalLevelLoader.NetcodePatcher; using LethalLevelLoader.Tools; using LethalLib.Modules; using LethalModDataLib.Base; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LethalLevelLoader")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A Custom API to support the manual and dynamic integration of custom levels and dungeons in Lethal Company.")] [assembly: AssemblyFileVersion("1.6.0.0")] [assembly: AssemblyInformationalVersion("1.6.0+a7a027949ded1f533cda6ca5a34cec2c05efa808")] [assembly: AssemblyProduct("LethalLevelLoader")] [assembly: AssemblyTitle("LethalLevelLoader")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/IAmBatby/LethalLevelLoader/")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] 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; } } } public enum ContentType { Vanilla, Custom, Any, External } internal static class HookHelper { public class DisposableHookCollection { private List<ILHook> ilHooks = new List<ILHook>(); private List<Hook> hooks = new List<Hook>(); public void Clear() { foreach (Hook hook in hooks) { hook.Dispose(); } hooks.Clear(); foreach (ILHook ilHook in ilHooks) { ilHook.Dispose(); } ilHooks.Clear(); } public void ILHook<T>(string methodName, Manipulator to, Type[] parameters = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown ilHooks.Add(new ILHook((MethodBase)EzGetMethod<T>(methodName, parameters), to)); } public void Hook<T>(string methodName, Delegate to, Type[] parameters = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown hooks.Add(new Hook((MethodBase)EzGetMethod<T>(methodName, parameters), to)); } } public static MethodInfo methodof(Delegate method) { return method.Method; } public static MethodInfo EzGetMethod(Type type, string name, Type[] parameters = null) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; if (parameters == null) { return type.GetMethod(name, bindingAttr); } return type.GetMethod(name, bindingAttr, null, parameters, null); } public static MethodInfo EzGetMethod<T>(string name, Type[] parameters = null) { return EzGetMethod(typeof(T), name, parameters); } } public static class NetworkScenePatcher { [CompilerGenerated] private static class <>O { public static Action<Action<NetworkSceneManager>, NetworkSceneManager> <0>__GenerateScenesInBuild_Hook; public static Func<Func<NetworkSceneManager, uint, string>, NetworkSceneManager, uint, string> <1>__SceneNameFromHash_Hook; public static Func<Func<NetworkSceneManager, int, string, LoadSceneMode, bool>, NetworkSceneManager, int, string, LoadSceneMode, bool> <2>__ValidateSceneBeforeLoading_Hook; public static Manipulator <3>__ReplaceBuildIndexByScenePath; public static Manipulator <4>__ReplaceScenePathByBuildIndex; public static Func<int, string> <5>__GetScenePathByBuildIndex; public static Func<string, int> <6>__GetBuildIndexByScenePath; } private static List<string> scenePaths = new List<string>(); internal static Dictionary<string, int> scenePathToBuildIndex = new Dictionary<string, int>(); internal static Dictionary<int, string> buildIndexToScenePath = new Dictionary<int, string>(); private static Dictionary<uint, string> sceneHashToScenePath = new Dictionary<uint, string>(); private static Dictionary<int, string> levelSceneDict = new Dictionary<int, string>(); private static Dictionary<int, string> fullSceneIndexToPathDict = new Dictionary<int, string>(); private static Dictionary<string, int> fullScenePathToIndexDict = new Dictionary<string, int>(); private static HookHelper.DisposableHookCollection hooks = new HookHelper.DisposableHookCollection(); internal static bool patched { get; private set; } public static Dictionary<int, string> GetLevelSceneDict() { return new Dictionary<int, string>(levelSceneDict); } public static void AddScenePath(string scenePath) { if (!scenePaths.Contains(scenePath)) { DebugHelper.Log("Adding ScenePath: " + scenePath, DebugType.Developer); scenePaths.Add(scenePath); } } public static bool TryGetSceneIndex(int levelSceneIndex, string levelScenePath, out int sceneIndex) { sceneIndex = -1; int[] array = levelSceneDict.Keys.ToArray(); if (levelSceneDict.TryGetValue(array[levelSceneIndex], out var value)) { if (value == levelScenePath) { if (fullScenePathToIndexDict.TryGetValue(levelScenePath, out var value2)) { sceneIndex = value2; } else { DebugHelper.LogError("Failed At Full Scene Path", DebugType.User); } } else { DebugHelper.LogError("Failed At Path. Path 1: " + levelScenePath + ", Path 2: " + value, DebugType.User); } } else { DebugHelper.LogError("Failed At Level Scene Dict", DebugType.User); } return sceneIndex != -1; } internal static void Patch() { //IL_00d5: 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_00e0: Expected O, but got Unknown //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_010b: Expected O, but got Unknown //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_0136: Expected O, but got Unknown if (!patched) { patched = true; hooks.Hook<NetworkSceneManager>("GenerateScenesInBuild", new Action<Action<NetworkSceneManager>, NetworkSceneManager>(GenerateScenesInBuild_Hook)); hooks.Hook<NetworkSceneManager>("SceneNameFromHash", new Func<Func<NetworkSceneManager, uint, string>, NetworkSceneManager, uint, string>(SceneNameFromHash_Hook)); hooks.Hook<NetworkSceneManager>("ValidateSceneBeforeLoading", new Func<Func<NetworkSceneManager, int, string, LoadSceneMode, bool>, NetworkSceneManager, int, string, LoadSceneMode, bool>(ValidateSceneBeforeLoading_Hook), new Type[3] { typeof(int), typeof(string), typeof(LoadSceneMode) }); HookHelper.DisposableHookCollection disposableHookCollection = hooks; object obj = <>O.<3>__ReplaceBuildIndexByScenePath; if (obj == null) { Manipulator val = ReplaceBuildIndexByScenePath; <>O.<3>__ReplaceBuildIndexByScenePath = val; obj = (object)val; } disposableHookCollection.ILHook<NetworkSceneManager>("SceneHashFromNameOrPath", (Manipulator)obj); HookHelper.DisposableHookCollection disposableHookCollection2 = hooks; object obj2 = <>O.<3>__ReplaceBuildIndexByScenePath; if (obj2 == null) { Manipulator val2 = ReplaceBuildIndexByScenePath; <>O.<3>__ReplaceBuildIndexByScenePath = val2; obj2 = (object)val2; } disposableHookCollection2.ILHook<NetworkSceneManager>("ValidateSceneEvent", (Manipulator)obj2); HookHelper.DisposableHookCollection disposableHookCollection3 = hooks; object obj3 = <>O.<4>__ReplaceScenePathByBuildIndex; if (obj3 == null) { Manipulator val3 = ReplaceScenePathByBuildIndex; <>O.<4>__ReplaceScenePathByBuildIndex = val3; obj3 = (object)val3; } disposableHookCollection3.ILHook<NetworkSceneManager>("ScenePathFromHash", (Manipulator)obj3); } } internal static void Unpatch() { if (patched) { patched = false; hooks.Clear(); } } private static void ReplaceScenePathByBuildIndex(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); MethodInfo methodInfo = HookHelper.methodof(new Func<int, string>(GetScenePathByBuildIndex)); while (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchCall(instr, typeof(SceneUtility), "GetScenePathByBuildIndex") })) { val.Remove(); val.Emit(OpCodes.Call, (MethodBase)methodInfo); } } private static void ReplaceBuildIndexByScenePath(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); MethodInfo methodInfo = HookHelper.methodof(new Func<string, int>(GetBuildIndexByScenePath)); while (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchCall(instr, typeof(SceneUtility), "GetBuildIndexByScenePath") })) { val.Remove(); val.Emit(OpCodes.Call, (MethodBase)methodInfo); } } private static string GetScenePathByBuildIndex(int buildIndex) { if (buildIndexToScenePath.ContainsKey(buildIndex)) { return buildIndexToScenePath[buildIndex]; } return SceneUtility.GetScenePathByBuildIndex(buildIndex); } private static int GetBuildIndexByScenePath(string scenePath) { int num = SceneUtility.GetBuildIndexByScenePath(scenePath); if (num == -1 && scenePathToBuildIndex.ContainsKey(scenePath)) { num = scenePathToBuildIndex[scenePath]; } return num; } private static void GenerateScenesInBuild_Hook(Action<NetworkSceneManager> orig, NetworkSceneManager self) { scenePathToBuildIndex.Clear(); buildIndexToScenePath.Clear(); sceneHashToScenePath.Clear(); fullScenePathToIndexDict.Clear(); fullSceneIndexToPathDict.Clear(); levelSceneDict.Clear(); orig(self); for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) { string scenePathByBuildIndex = SceneUtility.GetScenePathByBuildIndex(i); fullSceneIndexToPathDict.Add(i, scenePathByBuildIndex); fullScenePathToIndexDict.Add(scenePathByBuildIndex, i); if (scenePathByBuildIndex.Contains("Level")) { levelSceneDict.Add(i, scenePathByBuildIndex); } } int sceneCountInBuildSettings = SceneManager.sceneCountInBuildSettings; for (int j = 0; j < scenePaths.Count; j++) { int num = sceneCountInBuildSettings + j; string text = scenePaths[j]; uint num2 = XXHash.Hash32(text); self.HashToBuildIndex.Add(num2, num); self.BuildIndexToHash.Add(num, num2); scenePathToBuildIndex.Add(text, num); buildIndexToScenePath.Add(num, text); sceneHashToScenePath.Add(num2, text); fullSceneIndexToPathDict.Add(num, text); fullScenePathToIndexDict.Add(text, num); levelSceneDict.Add(num, text); DebugHelper.Log("Added modded scene path: " + text, DebugType.Developer); } } private static string SceneNameFromHash_Hook(Func<NetworkSceneManager, uint, string> orig, NetworkSceneManager self, uint sceneHash) { if (sceneHash == 0) { return "No Scene"; } if (sceneHashToScenePath.ContainsKey(sceneHash)) { return sceneHashToScenePath[sceneHash]; } return orig(self, sceneHash); } private static bool ValidateSceneBeforeLoading_Hook(Func<NetworkSceneManager, int, string, LoadSceneMode, bool> orig, NetworkSceneManager self, int sceneIndex, string sceneName, LoadSceneMode loadSceneMode) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) bool flag = orig(self, sceneIndex, sceneName, loadSceneMode); return true; } } namespace LethalLevelLoader { public static class LethalBundleManager { public enum ModProcessingStatus { Inactive, Loading, Complete } private static List<AssetBundleGroup> assetBundleGroups = new List<AssetBundleGroup>(); private static Dictionary<AssetBundleGroup, List<ExtendedMod>> obtainedExtendedModsDict = new Dictionary<AssetBundleGroup, List<ExtendedMod>>(); private static List<ExtendedMod> obtainedExtendedModsList = new List<ExtendedMod>(); internal static Dictionary<string, List<Action<ExtendedMod>>> onExtendedModLoadedRequestDict = new Dictionary<string, List<Action<ExtendedMod>>>(); public static ModProcessingStatus CurrentStatus { get; internal set; } = ModProcessingStatus.Inactive; public static ExtendedEvent OnFinishedProcessing { get; private set; } = new ExtendedEvent(); public static bool HasFinalisedFoundContent { get; internal set; } internal static void Start() { DebugHelper.Log("LethalBundleManger: Starting!", DebugType.User); PatchedContent.VanillaMod = ExtendedMod.Create("LethalCompany", "Zeekerss"); ReadKnownSceneBundles(); TryLoadLethalBundles(); } private static void ReadKnownSceneBundles() { if (!File.Exists(LethalLevelLoader.AssetBundles.AssetBundleLoader.KnownSceneBundlesPath)) { return; } string[] array = File.ReadAllLines(LethalLevelLoader.AssetBundles.AssetBundleLoader.KnownSceneBundlesPath); if (array.Length < 1 || !int.TryParse(array[0], out var result) || result != LethalBundleManifest.ManifestVersion) { DebugHelper.LogWarning("Invalid or different manifest version found, it will be remade.'", DebugType.User); return; } for (int i = 1; i < array.Length; i++) { LethalBundleManifest value = new LethalBundleManifest(array[i]); LethalLevelLoader.AssetBundles.AssetBundleLoader.knownSceneBundles.TryAdd(value.fileName, value); } } private static void WriteKnownSceneBundles() { List<string> list = new List<string> { LethalBundleManifest.ManifestVersion.ToString() }; list.AddRange(LethalLevelLoader.AssetBundles.AssetBundleLoader.knownSceneBundles.Values.Select((LethalBundleManifest manifest) => manifest.ToString())); File.WriteAllLines(LethalLevelLoader.AssetBundles.AssetBundleLoader.KnownSceneBundlesPath, list, Encoding.UTF8); LethalLevelLoader.AssetBundles.AssetBundleLoader.knownSceneBundles = null; } private static bool TryLoadLethalBundles() { DebugHelper.Log("LethalBundleManger: Now Loading Bundles!", DebugType.User); if (LethalLevelLoader.AssetBundles.AssetBundleLoader.LoadAllBundlesRequest(null, null, ".lethalbundle", OnAssetBundleGroupCreated)) { CurrentStatus = ModProcessingStatus.Loading; LethalLevelLoader.AssetBundles.AssetBundleLoader.OnBundlesFinishedProcessing.AddListener(OnAssetBundleLoadRequestFinished); return true; } return false; } private static void OnAssetBundleGroupCreated(AssetBundleGroup newGroup) { DebugHelper.Log("LethalBundleManger Recieved Group: " + newGroup.GroupName, DebugType.User); FindContentInAssetBundleGroup(newGroup); } private static void OnAssetBundleLoadRequestFinished() { DebugHelper.Log("LethalBundleManger Finished Requested Load", DebugType.User); LethalLevelLoader.AssetBundles.AssetBundleLoader.OnBundlesFinishedProcessing.RemoveListener(OnAssetBundleLoadRequestFinished); FinialiseFoundContent(); } private static void FindContentInAssetBundleGroup(AssetBundleGroup group) { List<ExtendedMod> list = group.LoadAllAssets<ExtendedMod>(); if (list.Count > 0) { foreach (ExtendedMod item in list) { RegisterExtendedMod(item, group); } return; } foreach (ExtendedContent item2 in group.LoadAllAssets<ExtendedContent>()) { RegisterNewExtendedContent(item2, group); } } internal static void RegisterExtendedMod(ExtendedMod extendedMod, AssetBundleGroup source) { DebugHelper.Log("Found ExtendedMod: " + ((Object)extendedMod).name, DebugType.User); extendedMod.ModNameAliases.Add(extendedMod.ModName); ExtendedMod extendedMod2 = null; foreach (ExtendedMod obtainedExtendedMods in obtainedExtendedModsList) { if (extendedMod.ModMergeSetting == ModMergeSetting.MatchingModName && obtainedExtendedMods.ModMergeSetting == ModMergeSetting.MatchingModName) { if (obtainedExtendedMods.ModName == extendedMod.ModName) { extendedMod2 = obtainedExtendedMods; } } else if (extendedMod.ModMergeSetting == ModMergeSetting.MatchingAuthorName && obtainedExtendedMods.ModMergeSetting == ModMergeSetting.MatchingAuthorName && obtainedExtendedMods.AuthorName == extendedMod.AuthorName) { extendedMod2 = obtainedExtendedMods; } } if ((Object)(object)extendedMod2 != (Object)null) { if (!extendedMod2.ModName.Contains(extendedMod2.AuthorName)) { DebugHelper.Log("Renaming ExtendedMod: " + extendedMod2.ModName + " To: " + extendedMod2.AuthorName + "sMod Due To Upcoming ExtendedMod Merge!", DebugType.Developer); extendedMod2.ModNameAliases.Add(extendedMod.ModName); extendedMod2.ModName = extendedMod2.AuthorName + "sMod"; } DebugHelper.Log("Merging ExtendedMod: " + extendedMod.ModName + " (" + extendedMod.AuthorName + ") With Already Obtained ExtendedMod: " + extendedMod2.ModName + " (" + extendedMod2.AuthorName + ")", DebugType.Developer); { foreach (ExtendedContent extendedContent in extendedMod.ExtendedContents) { try { extendedMod2.RegisterExtendedContent(extendedContent); } catch (Exception exception) { DebugHelper.LogError(exception, DebugType.User); } } return; } } obtainedExtendedModsList.Add(extendedMod); if (source != null) { if (obtainedExtendedModsDict.TryGetValue(source, out var value)) { if (!value.Contains(extendedMod)) { value.Add(extendedMod); } } else { obtainedExtendedModsDict.Add(source, new List<ExtendedMod> { extendedMod }); } } List<ExtendedContent> list = new List<ExtendedContent>(extendedMod.ExtendedContents); extendedMod.UnregisterAllExtendedContent(); foreach (ExtendedContent item in list) { try { extendedMod.RegisterExtendedContent(item); } catch (Exception exception2) { DebugHelper.LogError(exception2, DebugType.User); } } } internal static void RegisterNewExtendedContent(ExtendedContent extendedContent, AssetBundleGroup source) { if ((Object)(object)extendedContent == (Object)null) { DebugHelper.LogError("Failed to register new ExtendedContent as it was null!", DebugType.User); return; } string contentSourceName = ((source == null) ? ((Object)extendedContent).name : source.GroupName); ExtendedMod extendedMod = null; if (extendedContent is ExtendedLevel extendedLevel) { if (string.IsNullOrEmpty(extendedLevel.contentSourceName)) { extendedLevel.contentSourceName = contentSourceName; } extendedMod = GetOrCreateExtendedMod(source, extendedLevel.contentSourceName); } else if (extendedContent is ExtendedDungeonFlow extendedDungeonFlow) { if (string.IsNullOrEmpty(extendedDungeonFlow.contentSourceName)) { extendedDungeonFlow.contentSourceName = contentSourceName; } extendedMod = GetOrCreateExtendedMod(source, extendedDungeonFlow.contentSourceName); } else if (extendedContent is ExtendedItem extendedItem) { extendedMod = GetOrCreateExtendedMod(source, extendedItem.Item.itemName.RemoveWhitespace()); } else if (extendedContent is ExtendedEnemyType extendedEnemyType) { extendedMod = GetOrCreateExtendedMod(source, extendedEnemyType.EnemyType.enemyName.RemoveWhitespace()); } else { ExtendedWeatherEffect extendedWeatherEffect = extendedContent as ExtendedWeatherEffect; if (extendedWeatherEffect == null) { if (extendedContent is ExtendedBuyableVehicle extendedBuyableVehicle) { extendedMod = GetOrCreateExtendedMod(source, ((Object)extendedBuyableVehicle).name); } else if (extendedContent is ExtendedUnlockableItem extendedUnlockableItem) { extendedMod = GetOrCreateExtendedMod(source, ((Object)extendedUnlockableItem).name); } } } if (!((Object)(object)extendedMod != (Object)null)) { return; } try { extendedMod.RegisterExtendedContent(extendedContent); } catch (Exception exception) { DebugHelper.LogError(exception, DebugType.User); } } internal static ExtendedMod GetOrCreateExtendedMod(AssetBundleGroup source, string contentSourceName) { if (source == null) { DebugHelper.Log("Creating New ExtendedMod: " + contentSourceName, DebugType.Developer); ExtendedMod extendedMod = ExtendedMod.Create(contentSourceName); obtainedExtendedModsList.Add(extendedMod); return extendedMod; } if (obtainedExtendedModsDict.TryGetValue(source, out var value)) { return value.First(); } DebugHelper.Log("Creating New ExtendedMod: " + contentSourceName, DebugType.Developer); ExtendedMod extendedMod2 = ExtendedMod.Create(contentSourceName); obtainedExtendedModsList.Add(extendedMod2); if (obtainedExtendedModsDict.TryGetValue(source, out var value2)) { if (!value2.Contains(extendedMod2)) { value2.Add(extendedMod2); } } else { obtainedExtendedModsDict.Add(source, new List<ExtendedMod> { extendedMod2 }); } return extendedMod2; } internal static void FinialiseFoundContent() { foreach (ExtendedMod obtainedExtendedMods in obtainedExtendedModsList) { PatchedContent.ExtendedMods.Add(obtainedExtendedMods); DebugHelper.DebugExtendedMod(obtainedExtendedMods); } PatchedContent.ExtendedMods = new List<ExtendedMod>(PatchedContent.ExtendedMods.OrderBy((ExtendedMod o) => o.ModName).ToList()); foreach (ExtendedMod extendedMod in PatchedContent.ExtendedMods) { extendedMod.SortRegisteredContent(); } foreach (KeyValuePair<string, List<Action<ExtendedMod>>> item in onExtendedModLoadedRequestDict) { foreach (ExtendedMod extendedMod2 in PatchedContent.ExtendedMods) { if (!extendedMod2.ModNameAliases.Contains(item.Key) && !(extendedMod2.AuthorName == item.Key)) { continue; } foreach (Action<ExtendedMod> item2 in item.Value) { item2(extendedMod2); } } } WriteKnownSceneBundles(); NetworkRegisterCustomScenes(); LethalLevelLoader.AssetBundles.AssetBundleLoader.ClearCache(); DebugHelper.Log("Custom Content Processed. Unlocking Main Menu.", DebugType.User); HasFinalisedFoundContent = true; CurrentStatus = ModProcessingStatus.Complete; OnFinishedProcessing.Invoke(); } internal static void NetworkRegisterCustomScenes() { List<string> list = new List<string>(); List<string> list2 = new List<string>(); for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) { list.Add(AssetBundleUtilities.GetSceneName(SceneUtility.GetScenePathByBuildIndex(i))); } foreach (AssetBundleGroup assetBundleGroup in LethalLevelLoader.AssetBundles.AssetBundleLoader.Instance.AssetBundleGroups) { foreach (LethalLevelLoader.AssetBundles.AssetBundleInfo assetBundleInfo in assetBundleGroup.GetAssetBundleInfos()) { foreach (string sceneName in assetBundleInfo.GetSceneNames()) { if (!list2.Contains(sceneName)) { list2.Add(sceneName); } } } } foreach (string item in list2) { if (!list.Contains(item)) { NetworkScenePatcher.AddScenePath(item); if (!PatchedContent.AllLevelSceneNames.Contains(item)) { PatchedContent.AllLevelSceneNames.Add(item); } } } foreach (string allLevelSceneName in PatchedContent.AllLevelSceneNames) { DebugHelper.Log("Loaded SceneName: " + allLevelSceneName, DebugType.Developer); } } } [CreateAssetMenu(fileName = "ExtendedBuyableVehicle", menuName = "Lethal Level Loader/Extended Content/ExtendedBuyableVehicle", order = 21)] public class ExtendedBuyableVehicle : ExtendedContent { [field: SerializeField] public BuyableVehicle BuyableVehicle { get; set; } [field: SerializeField] public string TerminalKeywordName { get; set; } = string.Empty; public int VehicleID { get; set; } public TerminalNode VehicleBuyNode { get; set; } public TerminalNode VehicleBuyConfirmNode { get; set; } public TerminalNode VehicleInfoNode { get; set; } internal static ExtendedBuyableVehicle Create(BuyableVehicle newBuyableVehicle) { ExtendedBuyableVehicle extendedBuyableVehicle = ScriptableObject.CreateInstance<ExtendedBuyableVehicle>(); ((Object)extendedBuyableVehicle).name = ((Object)newBuyableVehicle.vehiclePrefab).name; extendedBuyableVehicle.BuyableVehicle = newBuyableVehicle; return extendedBuyableVehicle; } } public class ExtendedContent : ScriptableObject { public ExtendedMod ExtendedMod { get; internal set; } public ContentType ContentType { get; internal set; } public List<string> ContentTagStrings { get; internal set; } = new List<string>(); [field: SerializeField] public List<ContentTag> ContentTags { get; internal set; } = new List<ContentTag>(); public string ModName => ExtendedMod.ModName; public string AuthorName => ExtendedMod.AuthorName; public string UniqueIdentificationName => AuthorName.ToLowerInvariant() + "." + ModName.ToLowerInvariant() + "." + ((Object)this).name.ToLowerInvariant(); internal virtual void TryCreateMatchingProperties() { } public bool TryGetTag(string tag) { foreach (ContentTag contentTag in ContentTags) { if (contentTag.contentTagName == tag) { return true; } } return false; } public bool TryGetTag(string tag, out ContentTag returnTag) { returnTag = null; foreach (ContentTag contentTag in ContentTags) { if (contentTag.contentTagName == tag) { returnTag = contentTag; return true; } } return false; } public bool TryAddTag(string tag) { if (!TryGetTag(tag)) { ContentTags.Add(ContentTag.Create(tag)); return true; } return false; } } [Serializable] public class StringWithRarity { [SerializeField] private string _name; [SerializeField] [Range(0f, 300f)] private int _rarity; [HideInInspector] public string Name { get { return _name; } set { _name = value; } } [HideInInspector] public int Rarity { get { return _rarity; } set { _rarity = value; } } [HideInInspector] public StringWithRarity(string newName, int newRarity) { _name = newName; _rarity = newRarity; } } [Serializable] public class Vector2WithRarity { [SerializeField] private Vector2 _minMax; [SerializeField] private int _rarity; [HideInInspector] public float Min { get { return _minMax.x; } set { _minMax.x = value; } } [HideInInspector] public float Max { get { return _minMax.y; } set { _minMax.y = value; } } [HideInInspector] public int Rarity { get { return _rarity; } set { _rarity = value; } } public Vector2WithRarity(Vector2 vector2, int newRarity) { //IL_000c: 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) _minMax.x = vector2.x; _minMax.y = vector2.y; _rarity = newRarity; } public Vector2WithRarity(float newMin, float newMax, int newRarity) { _minMax.x = newMin; _minMax.y = newMax; _rarity = newRarity; } } [CreateAssetMenu(fileName = "ExtendedDungeonFlow", menuName = "Lethal Level Loader/Extended Content/ExtendedDungeonFlow", order = 21)] public class ExtendedDungeonFlow : ExtendedContent { [Space(5f)] [Tooltip("Overrides vanilla camera Far Plane Clip Distance, The highest value between current Level and Interior will be used.")] [Range(0f, 10000f)] [SerializeField] public float OverrideCameraMaxDistance = 400f; [Space(25f)] [Header("Obsolete (Legacy Fields, Will Be Removed In The Future)")] [Obsolete] public bool generateAutomaticConfigurationOptions = true; [Obsolete] public bool enableDynamicDungeonSizeRestriction; [Obsolete] public float dungeonSizeMin = 1f; [Obsolete] public float dungeonSizeMax = 1f; [Obsolete] [Range(0f, 1f)] public float dungeonSizeLerpPercentage = 1f; [Obsolete] public AudioClip dungeonFirstTimeAudio; [Obsolete] public DungeonFlow dungeonFlow; [Obsolete] public string dungeonDisplayName = string.Empty; [Obsolete] public string contentSourceName = string.Empty; [Obsolete] public List<StringWithRarity> dynamicLevelTagsList = new List<StringWithRarity>(); [Obsolete] public List<Vector2WithRarity> dynamicRoutePricesList = new List<Vector2WithRarity>(); [Obsolete] public List<StringWithRarity> dynamicCurrentWeatherList = new List<StringWithRarity>(); [Obsolete] public List<StringWithRarity> manualPlanetNameReferenceList = new List<StringWithRarity>(); [Obsolete] public List<StringWithRarity> manualContentSourceNameReferenceList = new List<StringWithRarity>(); [Obsolete] [HideInInspector] public int dungeonDefaultRarity; [field: Header("General Settings")] [field: SerializeField] public DungeonFlow DungeonFlow { get; set; } [field: SerializeField] public string DungeonName { get; set; } = string.Empty; [field: SerializeField] public float MapTileSize { get; set; } = 1f; [field: SerializeField] public AudioClip FirstTimeDungeonAudio { get; set; } [field: Space(5f)] [field: Header("Dynamic Injection Matching Settings")] [field: SerializeField] public LevelMatchingProperties LevelMatchingProperties { get; set; } [field: Space(5f)] [field: Header("Extended Feature Settings")] [field: Tooltip("When above Vector3.zero this value will restrict the max bounds of the interior.")] [field: SerializeField] public Vector3 OverrideRestrictedTilePlacementBounds { get; set; } = Vector3.zero; public bool OverrideTilePlacementBounds { get { //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) Vector3 overrideRestrictedTilePlacementBounds = OverrideRestrictedTilePlacementBounds; return ((Vector3)(ref overrideRestrictedTilePlacementBounds)).sqrMagnitude > 1f; } } [field: SerializeField] public GameObject OverrideKeyPrefab { get; set; } [field: SerializeField] public List<SpawnableMapObject> SpawnableMapObjects { get; set; } = new List<SpawnableMapObject>(); [field: SerializeField] public List<GlobalPropCountOverride> GlobalPropCountOverridesList { get; set; } = new List<GlobalPropCountOverride>(); [field: Space(5f)] [field: SerializeField] public bool IsDynamicDungeonSizeRestrictionEnabled { get; set; } [field: SerializeField] public Vector2 DynamicDungeonSizeMinMax { get; set; } = new Vector2(1f, 1f); [field: SerializeField] [field: Range(0f, 1f)] public float DynamicDungeonSizeLerpRate { get; set; } = 1f; public float DynamicDungeonSizeMin => DynamicDungeonSizeMinMax.x; public float DynamicDungeonSizeMax => DynamicDungeonSizeMinMax.y; [field: Tooltip("Lower the kill floor of any Level this Dungeon generates on down to the lowest point of the generation.")] [field: SerializeField] public bool IsDynamicOutOfBoundsTriggerEnabled { get; set; } [field: Space(10f)] [field: Header("Misc. Settings")] [field: SerializeField] public bool GenerateAutomaticConfigurationOptions { get; set; } = true; public int DungeonID { get; internal set; } public bool IsCurrentDungeon => (Object)(object)DungeonManager.CurrentExtendedDungeonFlow == (Object)(object)this; [HideInInspector] public DungeonEvents DungeonEvents { get; internal set; } = new DungeonEvents(); internal static ExtendedDungeonFlow Create(DungeonFlow newDungeonFlow, AudioClip newFirstTimeDungeonAudio) { ExtendedDungeonFlow extendedDungeonFlow = ScriptableObject.CreateInstance<ExtendedDungeonFlow>(); extendedDungeonFlow.DungeonFlow = newDungeonFlow; extendedDungeonFlow.FirstTimeDungeonAudio = newFirstTimeDungeonAudio; if ((Object)(object)extendedDungeonFlow.LevelMatchingProperties == (Object)null) { extendedDungeonFlow.LevelMatchingProperties = LevelMatchingProperties.Create(extendedDungeonFlow); } return extendedDungeonFlow; } internal void Initialize() { if ((Object)(object)LevelMatchingProperties == (Object)null) { LevelMatchingProperties = LevelMatchingProperties.Create(this); } GetDungeonFlowID(); if (DungeonName == null || DungeonName == string.Empty) { DungeonName = ((Object)DungeonFlow).name; } ((Object)this).name = ((Object)DungeonFlow).name.Replace("Flow", "") + "ExtendedDungeonFlow"; if ((Object)(object)FirstTimeDungeonAudio == (Object)null) { DebugHelper.LogWarning("Custom Dungeon: " + DungeonName + " Is Missing A DungeonFirstTimeAudio Reference! Assigning Facility Audio To Prevent Errors.", DebugType.Developer); FirstTimeDungeonAudio = Patches.RoundManager.firstTimeDungeonAudios[0]; } } private void GetDungeonFlowID() { if (base.ContentType == ContentType.Custom) { DungeonID = PatchedContent.ExtendedDungeonFlows.Count; } if (base.ContentType != 0) { return; } IndoorMapType[] dungeonFlowTypes = Patches.RoundManager.dungeonFlowTypes; foreach (IndoorMapType val in dungeonFlowTypes) { if ((Object)(object)val.dungeonFlow == (Object)(object)DungeonFlow) { DungeonID = Patches.RoundManager.dungeonFlowTypes.ToList().IndexOf(val); } } } internal override void TryCreateMatchingProperties() { if ((Object)(object)LevelMatchingProperties == (Object)null) { LevelMatchingProperties = LevelMatchingProperties.Create(this); } LevelMatchingProperties.ApplyValues(null, manualContentSourceNameReferenceList, newPlanetNames: manualPlanetNameReferenceList, newLevelTags: dynamicLevelTagsList, newRoutePrices: dynamicRoutePricesList, newCurrentWeathers: dynamicCurrentWeatherList); } internal void ConvertObsoleteValues() { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)DungeonFlow == (Object)null && (Object)(object)dungeonFlow != (Object)null) { DebugHelper.LogWarning("ExtendedDungeonFlow.dungeonFlow is Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.DungeonFlow instead.", DebugType.Developer); DungeonFlow = dungeonFlow; dungeonFlow = null; } if (string.IsNullOrEmpty(DungeonName) && !string.IsNullOrEmpty(dungeonDisplayName)) { DebugHelper.LogWarning("ExtendedDungeonFlow.dungeonDisplayName is Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.DungeonName instead.", DebugType.Developer); DungeonName = dungeonDisplayName; dungeonDisplayName = string.Empty; } if ((Object)(object)FirstTimeDungeonAudio == (Object)null && (Object)(object)dungeonFirstTimeAudio != (Object)null) { DebugHelper.LogWarning("ExtendedDungeonFlow.dungeonFirstTimeAudio is Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.FirstTimeDungeonAudio instead.", DebugType.Developer); FirstTimeDungeonAudio = dungeonFirstTimeAudio; dungeonFirstTimeAudio = null; } if (dungeonSizeLerpPercentage != 1f) { DebugHelper.LogWarning("ExtendedDungeonFlow.dungeonSizeLerpPercentage is Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.DynamicDungeonSizeLerpRate instead.", DebugType.Developer); } if (dungeonSizeMax != 1f || dungeonSizeMin != 1f) { DebugHelper.LogWarning("ExtendedDungeonFlow.dungeonSizeMin and ExtendedDungeonFlow.dungeonSizeMax are Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.DynamicSungeonSizeMinMax instead.", DebugType.Developer); DynamicDungeonSizeMinMax = new Vector2(dungeonSizeMin, dungeonSizeMax); } if (!string.IsNullOrEmpty(contentSourceName)) { DebugHelper.LogWarning("ExtendedDungeonFlow.contentSourceName is Obsolete and will be removed in following releases, Please use ExtendedMod.AuthorName instead.", DebugType.Developer); } if ((Object)(object)LevelMatchingProperties == (Object)null && (dynamicLevelTagsList.Count > 0 || dynamicRoutePricesList.Count > 0 || dynamicCurrentWeatherList.Count > 0 || manualContentSourceNameReferenceList.Count > 0 || manualContentSourceNameReferenceList.Count > 0)) { DebugHelper.LogWarning("ExtendedDungeonFlow dynamic and manual match reference lists are Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.LevelMatchingProperties instead.", DebugType.Developer); TryCreateMatchingProperties(); } if (enableDynamicDungeonSizeRestriction || IsDynamicDungeonSizeRestrictionEnabled != enableDynamicDungeonSizeRestriction) { DebugHelper.LogWarning("ExtendedDungeonFlow.enableDynamicDungeonSizeRestriction Is Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.IsDynamicDungeonRestrictionEnabled instead.", DebugType.Developer); IsDynamicDungeonSizeRestrictionEnabled = enableDynamicDungeonSizeRestriction; } if (!generateAutomaticConfigurationOptions || GenerateAutomaticConfigurationOptions != generateAutomaticConfigurationOptions) { DebugHelper.LogWarning("ExtendedDungeonFlow.generateAutomaticConfigurationOptions Is Obsolete and will be removed in following releases, Please use ExtendedDungeonFlow.GenerateAutomaticConfigurationOptions instead.", DebugType.Developer); GenerateAutomaticConfigurationOptions = generateAutomaticConfigurationOptions; } } } [Serializable] public class GlobalPropCountOverride { public int globalPropID; [Range(0f, 1f)] public float globalPropCountScaleRate; } [Serializable] public class DungeonEvents { public ExtendedEvent<RoundManager> onBeforeDungeonGenerate = new ExtendedEvent<RoundManager>(); public ExtendedEvent onShipLand = new ExtendedEvent(); public ExtendedEvent onShipLeave = new ExtendedEvent(); public ExtendedEvent<List<GameObject>> onSpawnedSyncedObjects = new ExtendedEvent<List<GameObject>>(); public ExtendedEvent<List<GameObject>> onSpawnedMapObjects = new ExtendedEvent<List<GameObject>>(); public ExtendedEvent<List<GrabbableObject>> onSpawnedScrapObjects = new ExtendedEvent<List<GrabbableObject>>(); public ExtendedEvent<(EnemyVent, EnemyAI)> onEnemySpawnedFromVent = new ExtendedEvent<(EnemyVent, EnemyAI)>(); public ExtendedEvent<(EntranceTeleport, PlayerControllerB)> onPlayerEnterDungeon = new ExtendedEvent<(EntranceTeleport, PlayerControllerB)>(); public ExtendedEvent<(EntranceTeleport, PlayerControllerB)> onPlayerExitDungeon = new ExtendedEvent<(EntranceTeleport, PlayerControllerB)>(); public ExtendedEvent<bool> onPowerSwitchToggle = new ExtendedEvent<bool>(); public ExtendedEvent<LungProp> onApparatusTaken = new ExtendedEvent<LungProp>(); } [CreateAssetMenu(fileName = "ExtendedEnemyType", menuName = "Lethal Level Loader/Extended Content/ExtendedEnemyType", order = 24)] public class ExtendedEnemyType : ExtendedContent { [field: Header("General Settings")] [field: SerializeField] public EnemyType EnemyType { get; set; } [field: SerializeField] public string EnemyDisplayName { get; set; } [field: Space(5f)] [field: Header("Dynamic Injection Matching Settings")] [field: SerializeField] public LevelMatchingProperties OutsideLevelMatchingProperties { get; set; } [field: SerializeField] public LevelMatchingProperties DaytimeLevelMatchingProperties { get; set; } [field: SerializeField] public LevelMatchingProperties InsideLevelMatchingProperties { get; set; } [field: SerializeField] public DungeonMatchingProperties InsideDungeonMatchingProperties { get; set; } [field: Space(5f)] [field: Header("Terminal Bestiary Override Settings")] [field: SerializeField] [field: TextArea(2, 20)] public string InfoNodeDescription { get; set; } = string.Empty; [field: SerializeField] public VideoClip InfoNodeVideoClip { get; set; } public ScanNodeProperties ScanNodeProperties { get; internal set; } public int EnemyID { get; internal set; } public TerminalNode EnemyInfoNode { get; internal set; } public static ExtendedEnemyType Create(EnemyType enemyType, ExtendedMod extendedMod, ContentType contentType) { ExtendedEnemyType extendedEnemyType = ScriptableObject.CreateInstance<ExtendedEnemyType>(); extendedEnemyType.EnemyType = enemyType; ((Object)extendedEnemyType).name = enemyType.enemyName.SkipToLetters().RemoveWhitespace() + "ExtendedEnemyType"; extendedEnemyType.ContentType = contentType; extendedMod.RegisterExtendedContent(extendedEnemyType); extendedEnemyType.TryCreateMatchingProperties(); return extendedEnemyType; } public void Initalize() { DebugHelper.Log("Initializing Custom Enemy: " + EnemyType.enemyName, DebugType.Developer); TryCreateMatchingProperties(); } internal override void TryCreateMatchingProperties() { if ((Object)(object)InsideLevelMatchingProperties == (Object)null) { InsideLevelMatchingProperties = LevelMatchingProperties.Create(this); } if ((Object)(object)InsideDungeonMatchingProperties == (Object)null) { InsideDungeonMatchingProperties = DungeonMatchingProperties.Create(this); } if ((Object)(object)OutsideLevelMatchingProperties == (Object)null) { OutsideLevelMatchingProperties = LevelMatchingProperties.Create(this); } if ((Object)(object)DaytimeLevelMatchingProperties == (Object)null) { DaytimeLevelMatchingProperties = LevelMatchingProperties.Create(this); } } } [CreateAssetMenu(fileName = "ExtendedFootstepSurface", menuName = "Lethal Level Loader/Extended Content/ExtendedFootstepSurface", order = 27)] public class ExtendedFootstepSurface : ExtendedContent { public FootstepSurface footstepSurface; public List<Material> associatedMaterials; } [CreateAssetMenu(fileName = "ExtendedItem", menuName = "Lethal Level Loader/Extended Content/ExtendedItem", order = 23)] public class ExtendedItem : ExtendedContent { [field: Header("General Settings")] [field: SerializeField] public Item Item { get; set; } [field: SerializeField] public string PluralisedItemName { get; set; } = string.Empty; [field: SerializeField] public bool IsBuyableItem { get; set; } [field: Space(5f)] [field: Header("Dynamic Injection Matching Settings")] [field: SerializeField] public LevelMatchingProperties LevelMatchingProperties { get; set; } [field: SerializeField] public DungeonMatchingProperties DungeonMatchingProperties { get; set; } [field: Space(5f)] [field: Header("Terminal Store & Info Override Settings")] [field: SerializeField] public string OverrideInfoNodeDescription { get; set; } = string.Empty; [field: SerializeField] public string OverrideBuyNodeDescription { get; set; } = string.Empty; [field: SerializeField] public string OverrideBuyConfirmNodeDescription { get; set; } = string.Empty; public TerminalNode BuyNode { get; internal set; } public TerminalNode BuyConfirmNode { get; internal set; } public TerminalNode BuyInfoNode { get; internal set; } public int CreditsWorth { get { if ((Object)(object)BuyNode != (Object)null && (Object)(object)BuyConfirmNode != (Object)null) { BuyNode.itemCost = Item.creditsWorth; BuyConfirmNode.itemCost = Item.creditsWorth; } else { Debug.LogWarning((object)"BuyNode And/Or BuyConfirm Node Missing!"); } return Item.creditsWorth; } set { if (value >= 0) { if ((Object)(object)BuyNode != (Object)null && (Object)(object)BuyConfirmNode != (Object)null) { BuyNode.itemCost = value; BuyConfirmNode.itemCost = value; } else { Debug.LogWarning((object)"BuyNode And/Or BuyConfirm Node Missing!"); } Item.creditsWorth = value; } } } public static ExtendedItem Create(Item newItem, ExtendedMod extendedMod, ContentType contentType) { ExtendedItem extendedItem = ScriptableObject.CreateInstance<ExtendedItem>(); extendedItem.Item = newItem; ((Object)extendedItem).name = newItem.itemName.SkipToLetters().RemoveWhitespace() + "ExtendedItem"; extendedItem.ContentType = contentType; extendedMod.RegisterExtendedContent(extendedItem); extendedItem.TryCreateMatchingProperties(); return extendedItem; } public void Initialize() { DebugHelper.Log("Initializing Custom Item: " + Item.itemName + ". Is Buyable: " + IsBuyableItem + ". Is Scrap: " + Item.isScrap, DebugType.Developer); TryCreateMatchingProperties(); if (!Patches.StartOfRound.allItemsList.itemsList.Contains(Item)) { Patches.StartOfRound.allItemsList.itemsList.Add(Item); } if (IsBuyableItem) { TerminalManager.CreateItemTerminalData(this); } } internal override void TryCreateMatchingProperties() { if ((Object)(object)LevelMatchingProperties == (Object)null) { LevelMatchingProperties = LevelMatchingProperties.Create(this); } if ((Object)(object)DungeonMatchingProperties == (Object)null) { DungeonMatchingProperties = DungeonMatchingProperties.Create(this); } } public void SetLevelMatchingProperties(LevelMatchingProperties newLevelMatchingProperties) { if ((Object)(object)Plugin.Instance != (Object)null) { Debug.LogError((object)"SetLevelMatchingProperties() Should Only Be Used In Editor!"); } LevelMatchingProperties = newLevelMatchingProperties; } } [CreateAssetMenu(fileName = "ExtendedLevel", menuName = "Lethal Level Loader/Extended Content/ExtendedLevel", order = 20)] public class ExtendedLevel : ExtendedContent { [Space(5f)] [SerializeField] private int routePrice; [Space(5f)] [Tooltip("Overrides vanilla camera Far Plane Clip Distance, The highest value between current Level and Interior will be used.")] [Range(0f, 10000f)] [SerializeField] public float OverrideCameraMaxDistance = 400f; [Space(25f)] [Header("Obsolete (Legacy Fields, Will Be Removed In The Future)")] [Obsolete] public SelectableLevel selectableLevel; [Obsolete] [Space(5f)] public string contentSourceName = string.Empty; [Obsolete] [Space(5f)] public List<string> levelTags = new List<string>(); [field: Header("General Settings")] [field: SerializeField] public SelectableLevel SelectableLevel { get; set; } [field: Header("Extended Feature Settings")] [field: SerializeField] public bool OverrideDynamicRiskLevelAssignment { get; set; } [field: Space(5f)] [field: SerializeField] public bool IsRouteHidden { get; set; } [field: SerializeField] public bool IsRouteLocked { get; set; } public bool IsRouteRemoved { get; set; } [field: SerializeField] public string LockedRouteNodeText { get; set; } = string.Empty; [field: Space(5f)] [field: SerializeField] public AnimationClip ShipFlyToMoonClip { get; set; } [field: SerializeField] public AnimationClip ShipFlyFromMoonClip { get; set; } [field: Space(5f)] [field: SerializeField] public List<StringWithRarity> SceneSelections { get; set; } = new List<StringWithRarity>(); [field: Space(5f)] [field: Header("Weather Effect Override Settings")] [field: SerializeField] public Vector3 OverrideDustStormVolumeSize { get; set; } = Vector3.zero; [field: Space(5f)] [field: SerializeField] public GameObject OverrideQuicksandPrefab { get; set; } [field: SerializeField] public GameObject OverrideRainPrefab { get; set; } [field: SerializeField] public AudioClip OverrideRainAmbience { get; set; } [field: Space(5f)] [field: SerializeField] public ParticleSystem OverrideStormyLightningStrikeExplosion { get; set; } [field: SerializeField] public ParticleSystem OverrideStormyStaticElectricityParticle { get; set; } [field: SerializeField] public AudioClip[] OverrideStormyLightningStrikeSFX { get; set; } [field: SerializeField] public AudioClip[] OverrideStormyDistantThunderSFX { get; set; } [field: SerializeField] public AudioClip OverrideStormyStaticElectricitySFX { get; set; } [field: Space(5f)] [field: SerializeField] public GameObject OverrideStormyRainPrefab { get; set; } [field: SerializeField] public AudioClip OverrideStormyRainAmbience { get; set; } [field: Space(5f)] [field: SerializeField] public Vector3 OverrideFoggyVolumeSize { get; set; } = Vector3.zero; [field: Space(5f)] [field: SerializeField] public GameObject OverrideFloodedPrefab { get; set; } [field: SerializeField] public AudioClip OverrideFloodedAmbience { get; set; } [field: Space(5f)] [field: SerializeField] public AudioClip OverrideEclipsedMusic { get; set; } [field: Space(5f)] [field: Header("Time Of Day Music Override Settings")] [field: SerializeField] public AudioClip OverrideStartOfDayMusic { get; set; } [field: SerializeField] public AudioClip OverrideMidDayMusic { get; set; } [field: SerializeField] public AudioClip OverrideLateDayMusic { get; set; } [field: SerializeField] public AudioClip OverrideNightMusic { get; set; } [field: Space(5f)] [field: Header("Terminal Route Override Settings")] [field: SerializeField] public string OverrideRouteNoun { get; set; } = string.Empty; [field: SerializeField] [field: TextArea(2, 20)] public string OverrideInfoNodeDescription { get; set; } = string.Empty; [field: SerializeField] [field: TextArea(2, 20)] public string OverrideRouteNodeDescription { get; set; } = string.Empty; [field: SerializeField] [field: TextArea(2, 20)] public string OverrideRouteConfirmNodeDescription { get; set; } = string.Empty; [field: Space(10f)] [field: Header("Misc. Settings")] [field: Space(5f)] [field: SerializeField] public bool GenerateAutomaticConfigurationOptions { get; set; } = true; public int RoutePrice { get { if ((Object)(object)RouteNode != (Object)null) { routePrice = RouteNode.itemCost; RouteConfirmNode.itemCost = routePrice; return RouteNode.itemCost; } DebugHelper.LogWarning("routeNode Is Missing! Using internal value!", DebugType.Developer); return routePrice; } set { if ((Object)(object)RouteNode != (Object)null && (Object)(object)RouteConfirmNode != (Object)null) { RouteNode.itemCost = value; RouteConfirmNode.itemCost = value; } else { DebugHelper.LogWarning("routeNode Is Missing! Only setting internal value!", DebugType.Developer); } routePrice = value; } } public string TerminalNoun { get { if (!string.IsNullOrEmpty(OverrideRouteNoun)) { return OverrideRouteNoun.StripSpecialCharacters().Sanitized(); } return NumberlessPlanetName.StripSpecialCharacters().Sanitized(); } } public string NumberlessPlanetName => GetNumberlessPlanetName(SelectableLevel); public int CalculatedDifficultyRating => LevelManager.CalculateExtendedLevelDifficultyRating(this); public bool IsCurrentLevel => (Object)(object)LevelManager.CurrentExtendedLevel == (Object)(object)this; public bool IsLevelLoaded { get { //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) Scene sceneByName = SceneManager.GetSceneByName(SelectableLevel.sceneName); return ((Scene)(ref sceneByName)).isLoaded; } } [HideInInspector] public LevelEvents LevelEvents { get; internal set; } = new LevelEvents(); public TerminalNode RouteNode { get; internal set; } public TerminalNode RouteConfirmNode { get; internal set; } public TerminalNode InfoNode { get; internal set; } public TerminalNode SimulateNode { get; internal set; } public List<ExtendedWeatherEffect> EnabledExtendedWeatherEffects { get; set; } = new List<ExtendedWeatherEffect>(); public ExtendedWeatherEffect CurrentExtendedWeatherEffect { get; set; } internal static ExtendedLevel Create(SelectableLevel newSelectableLevel) { ExtendedLevel extendedLevel = ScriptableObject.CreateInstance<ExtendedLevel>(); extendedLevel.SelectableLevel = newSelectableLevel; return extendedLevel; } internal void Initialize(string newContentSourceName, bool generateTerminalAssets) { bool flag = false; foreach (StringWithRarity sceneSelection in SceneSelections) { if (sceneSelection.Name == SelectableLevel.sceneName) { flag = true; } } if (!flag) { StringWithRarity item = new StringWithRarity(SelectableLevel.sceneName, 300); SceneSelections.Add(item); } foreach (StringWithRarity item2 in new List<StringWithRarity>(SceneSelections)) { if (!PatchedContent.AllLevelSceneNames.Contains(item2.Name)) { DebugHelper.LogWarning("Removing SceneSelection From: " + SelectableLevel.PlanetName + " As SceneName: " + item2.Name + " Is Not Loaded!", DebugType.Developer); SceneSelections.Remove(item2); } } if ((Object)(object)ShipFlyToMoonClip == (Object)null) { ShipFlyToMoonClip = LevelLoader.defaultShipFlyToMoonClip; } if ((Object)(object)ShipFlyFromMoonClip == (Object)null) { ShipFlyFromMoonClip = LevelLoader.defaultShipFlyFromMoonClip; } if ((Object)(object)OverrideQuicksandPrefab == (Object)null) { OverrideQuicksandPrefab = LevelLoader.defaultQuicksandPrefab; } ContentType contentType = base.ContentType; if ((contentType == ContentType.Custom || contentType == ContentType.External) ? true : false) { ((Object)this).name = NumberlessPlanetName.StripSpecialCharacters() + "ExtendedLevel"; ((Object)SelectableLevel).name = NumberlessPlanetName.StripSpecialCharacters() + "Level"; if (generateTerminalAssets) { TerminalManager.CreateLevelTerminalData(this, routePrice); } } if (base.ContentType == ContentType.Vanilla) { GetVanillaInfoNode(); } SetExtendedDungeonFlowMatches(); } internal void ConvertObsoleteValues() { if (levelTags.Count > 0 && base.ContentTags.Count == 0) { DebugHelper.LogWarning("ExtendedLevel.levelTags Is Obsolete and will be removed in following releases, Please use .ContentTags instead.", DebugType.Developer); foreach (ContentTag item in ContentTagManager.CreateNewContentTags(levelTags)) { base.ContentTags.Add(item); } } levelTags.Clear(); if ((Object)(object)SelectableLevel == (Object)null && (Object)(object)selectableLevel != (Object)null) { DebugHelper.LogWarning("ExtendedLevel.selectableLevel Is Obsolete and will be removed in following releases, Please use .SelectableLevel instead.", DebugType.Developer); SelectableLevel = selectableLevel; } if (!string.IsNullOrEmpty(contentSourceName)) { DebugHelper.LogWarning("ExtendedLevel.contentSourceName is Obsolete and will be removed in following releases, Please use ExtendedMod.AuthorName instead.", DebugType.Developer); } } internal static string GetNumberlessPlanetName(SelectableLevel selectableLevel) { if ((Object)(object)selectableLevel != (Object)null) { return new string(selectableLevel.PlanetName.SkipWhile((char c) => !char.IsLetter(c)).ToArray()); } return string.Empty; } internal void SetLevelID() { if (base.ContentType == ContentType.Custom) { SelectableLevel.levelID = PatchedContent.ExtendedLevels.IndexOf(this); if ((Object)(object)RouteNode != (Object)null) { RouteNode.displayPlanetInfo = SelectableLevel.levelID; } if ((Object)(object)RouteConfirmNode != (Object)null) { RouteConfirmNode.buyRerouteToMoon = SelectableLevel.levelID; } } } internal void SetExtendedDungeonFlowMatches() { IntWithRarity[] dungeonFlowTypes = SelectableLevel.dungeonFlowTypes; foreach (IntWithRarity val in dungeonFlowTypes) { if (DungeonManager.TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonFlowTypes[val.id].dungeonFlow, out var returnExtendedDungeonFlow)) { returnExtendedDungeonFlow.LevelMatchingProperties.planetNames.Add(new StringWithRarity(NumberlessPlanetName, val.rarity)); } } if (!(SelectableLevel.sceneName == "Level4March")) { return; } IndoorMapType[] dungeonFlowTypes2 = Patches.RoundManager.dungeonFlowTypes; foreach (IndoorMapType val2 in dungeonFlowTypes2) { if (((Object)val2.dungeonFlow).name == "Level1Flow3Exits" && DungeonManager.TryGetExtendedDungeonFlow(val2.dungeonFlow, out var returnExtendedDungeonFlow2)) { returnExtendedDungeonFlow2.LevelMatchingProperties.planetNames.Add(new StringWithRarity(NumberlessPlanetName, 300)); } } } internal void GetVanillaInfoNode() { CompatibleNoun[] compatibleNouns = TerminalManager.routeInfoKeyword.compatibleNouns; foreach (CompatibleNoun val in compatibleNouns) { if (val.noun.word == NumberlessPlanetName.ToLower()) { InfoNode = val.result; break; } } } public void ForceSetRoutePrice(int newValue) { if ((Object)(object)Plugin.Instance != (Object)null) { Debug.LogWarning((object)"ForceSetRoutePrice Should Only Be Used In Editor! Consider Using RoutePrice Property To Sync TerminalNode's With New Value."); } routePrice = newValue; } } [Serializable] public class LevelEvents { public ExtendedEvent onLevelLoaded = new ExtendedEvent(); public ExtendedEvent onShipLand = new ExtendedEvent(); public ExtendedEvent onShipLeave = new ExtendedEvent(); public ExtendedEvent<EnemyAI> onDaytimeEnemySpawn = new ExtendedEvent<EnemyAI>(); public ExtendedEvent<EnemyAI> onNighttimeEnemySpawn = new ExtendedEvent<EnemyAI>(); public ExtendedEvent<StoryLog> onStoryLogCollected = new ExtendedEvent<StoryLog>(); public ExtendedEvent<LungProp> onApparatusTaken = new ExtendedEvent<LungProp>(); public ExtendedEvent<(EntranceTeleport, PlayerControllerB)> onPlayerEnterDungeon = new ExtendedEvent<(EntranceTeleport, PlayerControllerB)>(); public ExtendedEvent<(EntranceTeleport, PlayerControllerB)> onPlayerExitDungeon = new ExtendedEvent<(EntranceTeleport, PlayerControllerB)>(); public ExtendedEvent<bool> onPowerSwitchToggle = new ExtendedEvent<bool>(); public ExtendedEvent<DayMode> onDayModeToggle = new ExtendedEvent<DayMode>(); } public enum ModMergeSetting { MatchingAuthorName, MatchingModName, Disabled } [CreateAssetMenu(fileName = "ExtendedMod", menuName = "Lethal Level Loader/ExtendedMod", order = 30)] public class ExtendedMod : ScriptableObject { [field: SerializeField] public string ModName { get; internal set; } = "Unspecified"; [field: SerializeField] public string AuthorName { get; internal set; } = "Unknown"; public List<string> ModNameAliases { get; internal set; } = new List<string>(); [field: SerializeField] public ModMergeSetting ModMergeSetting { get; internal set; } [field: SerializeField] public List<ExtendedLevel> ExtendedLevels { get; private set; } = new List<ExtendedLevel>(); [field: SerializeField] public List<ExtendedDungeonFlow> ExtendedDungeonFlows { get; private set; } = new List<ExtendedDungeonFlow>(); [field: SerializeField] public List<ExtendedItem> ExtendedItems { get; private set; } = new List<ExtendedItem>(); [field: SerializeField] public List<ExtendedEnemyType> ExtendedEnemyTypes { get; private set; } = new List<ExtendedEnemyType>(); [field: SerializeField] public List<ExtendedWeatherEffect> ExtendedWeatherEffects { get; private set; } = new List<ExtendedWeatherEffect>(); [field: SerializeField] public List<ExtendedFootstepSurface> ExtendedFootstepSurfaces { get; private set; } = new List<ExtendedFootstepSurface>(); [field: SerializeField] public List<ExtendedStoryLog> ExtendedStoryLogs { get; private set; } = new List<ExtendedStoryLog>(); [field: SerializeField] public List<ExtendedBuyableVehicle> ExtendedBuyableVehicles { get; private set; } = new List<ExtendedBuyableVehicle>(); [field: SerializeField] public List<ExtendedUnlockableItem> ExtendedUnlockableItems { get; private set; } = new List<ExtendedUnlockableItem>(); [field: SerializeField] public List<string> StreamingLethalBundleNames { get; private set; } = new List<string>(); public List<ExtendedContent> ExtendedContents { get { List<ExtendedContent> list = new List<ExtendedContent>(); foreach (ExtendedLevel extendedLevel in ExtendedLevels) { list.Add(extendedLevel); } foreach (ExtendedDungeonFlow extendedDungeonFlow in ExtendedDungeonFlows) { list.Add(extendedDungeonFlow); } foreach (ExtendedItem extendedItem in ExtendedItems) { list.Add(extendedItem); } foreach (ExtendedEnemyType extendedEnemyType in ExtendedEnemyTypes) { list.Add(extendedEnemyType); } foreach (ExtendedWeatherEffect extendedWeatherEffect in ExtendedWeatherEffects) { list.Add(extendedWeatherEffect); } foreach (ExtendedFootstepSurface extendedFootstepSurface in ExtendedFootstepSurfaces) { list.Add(extendedFootstepSurface); } foreach (ExtendedStoryLog extendedStoryLog in ExtendedStoryLogs) { list.Add(extendedStoryLog); } foreach (ExtendedBuyableVehicle extendedBuyableVehicle in ExtendedBuyableVehicles) { list.Add(extendedBuyableVehicle); } foreach (ExtendedUnlockableItem extendedUnlockableItem in ExtendedUnlockableItems) { list.Add(extendedUnlockableItem); } return list; } } internal static ExtendedMod Create(string modName) { ExtendedMod extendedMod = ScriptableObject.CreateInstance<ExtendedMod>(); extendedMod.ModName = modName; ((Object)extendedMod).name = modName.Sanitized() + "Mod"; DebugHelper.Log("Created New ExtendedMod: " + extendedMod.ModName, DebugType.Developer); return extendedMod; } public static ExtendedMod Create(string modName, string authorName) { ExtendedMod extendedMod = ScriptableObject.CreateInstance<ExtendedMod>(); extendedMod.ModName = modName; ((Object)extendedMod).name = modName.SkipToLetters().RemoveWhitespace() + "Mod"; extendedMod.AuthorName = authorName; if ((Object)(object)Plugin.Instance != (Object)null) { DebugHelper.Log("Created New ExtendedMod: " + extendedMod.ModName + " by " + authorName, DebugType.Developer); } return extendedMod; } public static ExtendedMod Create(string modName, string authorName, ExtendedContent[] extendedContents) { ExtendedMod extendedMod = ScriptableObject.CreateInstance<ExtendedMod>(); extendedMod.ModName = modName; ((Object)extendedMod).name = modName.SkipToLetters().RemoveWhitespace() + "Mod"; extendedMod.AuthorName = authorName; foreach (ExtendedContent newExtendedContent in extendedContents) { extendedMod.RegisterExtendedContent(newExtendedContent); } if ((Object)(object)Plugin.Instance != (Object)null) { DebugHelper.Log("Created New ExtendedMod: " + extendedMod.ModName + " by " + authorName, DebugType.Developer); } return extendedMod; } internal void RegisterExtendedContent(ExtendedContent newExtendedContent) { if ((Object)(object)newExtendedContent != (Object)null) { if (!ExtendedContents.Contains(newExtendedContent)) { if (newExtendedContent is ExtendedLevel extendedLevel) { RegisterExtendedContent(extendedLevel); return; } if (newExtendedContent is ExtendedDungeonFlow extendedDungeonFlow) { RegisterExtendedContent(extendedDungeonFlow); return; } if (newExtendedContent is ExtendedItem extendedItem) { RegisterExtendedContent(extendedItem); return; } if (newExtendedContent is ExtendedEnemyType extendedEnemyType) { RegisterExtendedContent(extendedEnemyType); return; } if (newExtendedContent is ExtendedWeatherEffect extendedWeatherEffect) { RegisterExtendedContent(extendedWeatherEffect); return; } if (newExtendedContent is ExtendedFootstepSurface extendedFootstepSurface) { RegisterExtendedContent(extendedFootstepSurface); return; } if (newExtendedContent is ExtendedStoryLog extendedStoryLog) { RegisterExtendedContent(extendedStoryLog); return; } if (newExtendedContent is ExtendedBuyableVehicle extendedBuyableVehicle) { RegisterExtendedContent(extendedBuyableVehicle); return; } if (newExtendedContent is ExtendedUnlockableItem extendedUnlockableItem) { RegisterExtendedContent(extendedUnlockableItem); return; } throw new ArgumentException("newExtendedContent", ((Object)newExtendedContent).name + " (" + ((object)newExtendedContent).GetType().Name + ") Could Not Be Registered To ExtendedMod: " + ModName + " Due To Unimplemented Registration Check!"); } throw new ArgumentException("newExtendedContent", ((Object)newExtendedContent).name + " (" + ((object)newExtendedContent).GetType().Name + ") Could Not Be Registered To ExtendedMod: " + ModName + " Due To Already Being Registered To This Mod!"); } throw new ArgumentNullException("newExtendedContent", "Null ExtendedContent Could Not Be Registered To ExtendedMod: " + ModName + " Due To Failed Validation Check!"); } internal void RegisterExtendedContent(ExtendedLevel extendedLevel) { extendedLevel.ConvertObsoleteValues(); TryThrowInvalidContentException(extendedLevel, Validators.ValidateExtendedContent(extendedLevel)); ExtendedLevels.Add(extendedLevel); extendedLevel.ContentTags.Add(ContentTag.Create("Custom")); extendedLevel.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedDungeonFlow extendedDungeonFlow) { extendedDungeonFlow.ConvertObsoleteValues(); TryThrowInvalidContentException(extendedDungeonFlow, Validators.ValidateExtendedContent(extendedDungeonFlow)); ExtendedDungeonFlows.Add(extendedDungeonFlow); extendedDungeonFlow.ContentTags.Add(ContentTag.Create("Custom")); extendedDungeonFlow.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedItem extendedItem) { TryThrowInvalidContentException(extendedItem, Validators.ValidateExtendedContent(extendedItem)); ExtendedItems.Add(extendedItem); extendedItem.ContentTags.Add(ContentTag.Create("Custom")); extendedItem.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedEnemyType extendedEnemyType) { TryThrowInvalidContentException(extendedEnemyType, Validators.ValidateExtendedContent(extendedEnemyType)); ExtendedEnemyTypes.Add(extendedEnemyType); extendedEnemyType.ContentTags.Add(ContentTag.Create("Custom")); extendedEnemyType.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedWeatherEffect extendedWeatherEffect) { TryThrowInvalidContentException(extendedWeatherEffect, Validators.ValidateExtendedContent(extendedWeatherEffect)); ExtendedWeatherEffects.Add(extendedWeatherEffect); extendedWeatherEffect.ContentTags.Add(ContentTag.Create("Custom")); extendedWeatherEffect.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedFootstepSurface extendedFootstepSurface) { TryThrowInvalidContentException(extendedFootstepSurface, Validators.ValidateExtendedContent(extendedFootstepSurface)); ExtendedFootstepSurfaces.Add(extendedFootstepSurface); extendedFootstepSurface.ContentTags.Add(ContentTag.Create("Custom")); extendedFootstepSurface.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedStoryLog extendedStoryLog) { TryThrowInvalidContentException(extendedStoryLog, Validators.ValidateExtendedContent(extendedStoryLog)); ExtendedStoryLogs.Add(extendedStoryLog); extendedStoryLog.ContentTags.Add(ContentTag.Create("Custom")); extendedStoryLog.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedBuyableVehicle extendedBuyableVehicle) { TryThrowInvalidContentException(extendedBuyableVehicle, Validators.ValidateExtendedContent(extendedBuyableVehicle)); ExtendedBuyableVehicles.Add(extendedBuyableVehicle); extendedBuyableVehicle.ContentTags.Add(ContentTag.Create("Custom")); extendedBuyableVehicle.ExtendedMod = this; } internal void RegisterExtendedContent(ExtendedUnlockableItem extendedUnlockableItem) { TryThrowInvalidContentException(extendedUnlockableItem, Validators.ValidateExtendedContent(extendedUnlockableItem)); ExtendedUnlockableItems.Add(extendedUnlockableItem); extendedUnlockableItem.ContentTags.Add(ContentTag.Create("Custom")); extendedUnlockableItem.ExtendedMod = this; } internal void TryThrowInvalidContentException(ExtendedContent extendedContent, (bool, string) result) { if (!result.Item1) { if ((Object)(object)extendedContent == (Object)null) { throw new ArgumentNullException("extendedContent", "Null ExtendedContent Could Not Be Registered To ExtendedMod: " + ModName + " Due To Failed Validation Check! " + result.Item2); } throw new ArgumentException("extendedContent", ((Object)extendedContent).name + " (" + ((object)extendedContent).GetType().Name + ") Could Not Be Registered To ExtendedMod: " + ModName + " Due To Failed Validation Check! " + result.Item2); } } internal void UnregisterExtendedContent(ExtendedContent currentExtendedContent) { if (currentExtendedContent is ExtendedLevel item) { ExtendedLevels.Remove(item); } else if (currentExtendedContent is ExtendedDungeonFlow item2) { ExtendedDungeonFlows.Remove(item2); } else if (currentExtendedContent is ExtendedItem item3) { ExtendedItems.Remove(item3); } else if (currentExtendedContent is ExtendedUnlockableItem item4) { ExtendedUnlockableItems.Remove(item4); } currentExtendedContent.ExtendedMod = null; DebugHelper.LogWarning("Unregistered ExtendedContent: " + ((Object)currentExtendedContent).name + " In ExtendedMod: " + ModName, DebugType.Developer); } internal void UnregisterAllExtendedContent() { ExtendedLevels.Clear(); ExtendedDungeonFlows.Clear(); ExtendedItems.Clear(); ExtendedEnemyTypes.Clear(); ExtendedWeatherEffects.Clear(); ExtendedFootstepSurfaces.Clear(); ExtendedStoryLogs.Clear(); ExtendedBuyableVehicles.Clear(); ExtendedUnlockableItems.Clear(); } internal void SortRegisteredContent() { ExtendedLevels.Sort((ExtendedLevel s1, ExtendedLevel s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedDungeonFlows.Sort((ExtendedDungeonFlow s1, ExtendedDungeonFlow s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedItems.Sort((ExtendedItem s1, ExtendedItem s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedEnemyTypes.Sort((ExtendedEnemyType s1, ExtendedEnemyType s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedWeatherEffects.Sort((ExtendedWeatherEffect s1, ExtendedWeatherEffect s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedFootstepSurfaces.Sort((ExtendedFootstepSurface s1, ExtendedFootstepSurface s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedStoryLogs.Sort((ExtendedStoryLog s1, ExtendedStoryLog s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedBuyableVehicles.Sort((ExtendedBuyableVehicle s1, ExtendedBuyableVehicle s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); ExtendedUnlockableItems.Sort((ExtendedUnlockableItem s1, ExtendedUnlockableItem s2) => ((Object)s1).name.CompareTo(((Object)s2).name)); } } [CreateAssetMenu(fileName = "ExtendedStoryLog", menuName = "Lethal Level Loader/Extended Content/ExtendedStoryLog", order = 26)] public class ExtendedStoryLog : ExtendedContent { public string sceneName = string.Empty; public int storyLogID; [Space(5f)] public string terminalKeywordNoun = string.Empty; [Space(5f)] public string storyLogTitle = string.Empty; [TextArea] public string storyLogDescription = string.Empty; [HideInInspector] internal int newStoryLogID; [HideInInspector] internal TerminalNode assignedNode; } [CreateAssetMenu(fileName = "ExtendedUnlockableItem", menuName = "Lethal Level Loader/Extended Content/ExtendedUnlockableItem", order = 21)] public class ExtendedUnlockableItem : ExtendedContent { [field: Header("General Settings")] [field: SerializeField] public UnlockableItem UnlockableItem { get; set; } [field: SerializeField] public int ItemCost { get; set; } [field: Space(5f)] [field: Header("Terminal Store & Info Override Settings")] [field: TextArea(2, 20)] [field: SerializeField] public string OverrideInfoNodeDescription { get; set; } = string.Empty; [field: TextArea(2, 20)] [field: SerializeField] public string OverrideBuyNodeDescription { get; set; } = string.Empty; [field: TextArea(2, 20)] [field: SerializeField] public string OverrideBuyConfirmNodeDescription { get; set; } = string.Empty; public int UnlockableItemID { get; set; } = -1; public TerminalNode BuyNode { get; internal set; } public TerminalNode BuyConfirmNode { get; internal set; } public TerminalNode BuyInfoNode { get; internal set; } public void Initialize() { TerminalManager.CreateUnlockableItemTerminalData(this); if (!Patches.StartOfRound.unlockablesList.unlockables.Contains(UnlockableItem)) { Patches.StartOfRound.unlockablesList.unlockables.Add(UnlockableItem); } } internal static ExtendedUnlockableItem Create(UnlockableItem newUnlockableItem, ExtendedMod extendedMod, ContentType contentType) { ExtendedUnlockableItem extendedUnlockableItem = ScriptableObject.CreateInstance<ExtendedUnlockableItem>(); extendedUnlockableItem.UnlockableItem = newUnlockableItem; ((Object)extendedUnlockableItem).name = newUnlockableItem.unlockableName.SkipToLetters().RemoveWhitespace() + "ExtendedUnlockableItem"; extendedUnlockableItem.ContentType = contentType; extendedMod.RegisterExtendedContent(extendedUnlockableItem); return extendedUnlockableItem; } } [CreateAssetMenu(fileName = "ExtendedWeatherEffect", menuName = "Lethal Level Loader/Extended Content/ExtendedWeatherEffect", order = 25)] public class ExtendedWeatherEffect : ExtendedContent { public ContentType contentType; [field: Header("General Settings")] [field: SerializeField] public LevelWeatherType BaseWeatherType { get; set; } = (LevelWeatherType)(-1); [field: SerializeField] public string WeatherDisplayName { get; set; } = string.Empty; [field: SerializeField] public GameObject WorldObject { get; set; } [field: SerializeField] public GameObject GlobalObject { get; set; } internal static ExtendedWeatherEffect Create(LevelWeatherType levelWeatherType, WeatherEffect weatherEffect, string weatherDisplayName, ContentType newContentType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Create(levelWeatherType, weatherEffect.effectObject, weatherEffect.effectPermanentObject, weatherDisplayName, newContentType); } internal static ExtendedWeatherEffect Create(LevelWeatherType levelWeatherType, GameObject worldObject, GameObject globalObject, string newWeatherDisplayName, ContentType newContentType) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) ExtendedWeatherEffect extendedWeatherEffect = ScriptableObject.CreateInstance<ExtendedWeatherEffect>(); extendedWeatherEffect.WeatherDisplayName = newWeatherDisplayName; ((Object)extendedWeatherEffect).name = extendedWeatherEffect.WeatherDisplayName + "ExtendedWeatherEffect"; extendedWeatherEffect.BaseWeatherType = levelWeatherType; extendedWeatherEffect.WorldObject = worldObject; extendedWeatherEffect.GlobalObject = globalObject; return extendedWeatherEffect; } } public class LLLSaveFile : ModDataContainer { public int parityStepsTaken; public Dictionary<int, AllItemsListItemData> itemSaveData = new Dictionary<int, AllItemsListItemData>(); public List<ExtendedLevelData> extendedLevelSaveData = new List<ExtendedLevelData>(); public string CurrentLevelName { get; internal set; } = string.Empty; public void Reset() { CurrentLevelName = string.Empty; parityStepsTaken = 0; itemSaveData = new Dictionary<int, AllItemsListItemData>(); extendedLevelSaveData = new List<ExtendedLevelData>(); } } public struct AllItemsListItemData { public string itemObjectName; public string itemName; public string modName; public string modAuthor; public int allItemsListIndex; public int modItemsListIndex; public int itemNameDuplicateIndex; public bool isScrap; public bool saveItemVariable; public AllItemsListItemData(string newItemObjectName, string newItemName, string newModName, string newModAuthor, int newAllItemsListIndex, int newModItemsListIndex, int newItemNameDuplicateIndex, bool newIsScrap, bool newSaveItemVariable) { itemObjectName = newItemObjectName; itemName = newItemName; modName = newModName; modAuthor = newModAuthor; allItemsListIndex = newAllItemsListIndex; modItemsListIndex = newModItemsListIndex; itemNameDuplicateIndex = newItemNameDuplicateIndex; isScrap = newIsScrap; saveItemVariable = newSaveItemVariable; } } public struct ExtendedLevelData : INetworkSerializable { public string uniqueIdentifier; public bool isHidden; public bool isLocked; public string UniqueIdentifier => uniqueIdentifier; public unsafe void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter { //IL_0018: 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_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) serializer.SerializeValue(ref uniqueIdentifier, false); ((BufferSerializer<bool>*)(&serializer))->SerializeValue<bool>(ref isHidden, default(ForPrimitives)); ((BufferSerializer<bool>*)(&serializer))->SerializeValue<bool>(ref isLocked, default(ForPrimitives)); } public ExtendedLevelData(ExtendedLevel extendedLevel) { uniqueIdentifier = string.Empty; uniqueIdentifier = extendedLevel.UniqueIdentificationName; isHidden = extendedLevel.IsRouteHidden; isLocked = extendedLevel.IsRouteLocked; } public void ApplySavedValues(ExtendedLevel extendedLevel) { extendedLevel.IsRouteHidden = isHidden; extendedLevel.IsRouteLocked = isLocked; } } [CreateAssetMenu(fileName = "ContentTag", menuName = "Lethal Level Loader/Utility/ContentTag", order = 11)] public class ContentTag : ScriptableObject { public string contentTagName; public Color contentTagColor; public static ContentTag Create(string tag, Color color) { //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) ContentTag contentTag = ScriptableObject.CreateInstance<ContentTag>(); contentTag.contentTagName = tag; contentTag.contentTagColor = color; ((Object)contentTag).name = tag + "ContentTag"; return contentTag; } public static ContentTag Create(string tag) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Create(tag, Color.white); } } [CreateAssetMenu(fileName = "DungeonMatchingProperties", menuName = "Lethal Level Loader/Utility/DungeonMatchingProperties", order = 13)] public class DungeonMatchingProperties : MatchingProperties { [Space(5f)] public List<StringWithRarity> dungeonTags = new List<StringWithRarity>(); [Space(5f)] public List<StringWithRarity> dungeonNames = new List<StringWithRarity>(); public new static DungeonMatchingProperties Create(ExtendedContent extendedContent) { DungeonMatchingProperties dungeonMatchingProperties = ScriptableObject.CreateInstance<DungeonMatchingProperties>(); ((Object)dungeonMatchingProperties).name = ((Object)extendedContent).name + "DungeonMatchingProperties"; return dungeonMatchingProperties; } public int GetDynamicRarity(ExtendedDungeonFlow extendedDungeonFlow) { int currentValue = 0; MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedTags(extendedDungeonFlow.ContentTags, dungeonNames), ((Object)extendedDungeonFlow).name, "Content Tags"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedString(extendedDungeonFlow.AuthorName, authorNames), ((Object)extendedDungeonFlow).name, "Author Name"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedStrings(extendedDungeonFlow.ExtendedMod.ModNameAliases, modNames), ((Object)extendedDungeonFlow).name, "Mod Name Name"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedString(((Object)extendedDungeonFlow.DungeonFlow).name, dungeonNames), ((Object)extendedDungeonFlow).name, "Dungeon Name"); return currentValue; } public void ApplyValues(List<StringWithRarity> newModNames = null, List<StringWithRarity> newAuthorNames = null, List<StringWithRarity> newDungeonTags = null, List<StringWithRarity> newDungeonNames = null) { if (newModNames != null && newModNames.Count != 0) { modNames = new List<StringWithRarity>(newModNames); } if (newAuthorNames != null && newAuthorNames.Count != 0) { authorNames = new List<StringWithRarity>(newAuthorNames); } if (newDungeonTags != null && newDungeonTags.Count != 0) { dungeonTags = new List<StringWithRarity>(newDungeonTags); } if (newDungeonNames != null && newDungeonNames.Count != 0) { dungeonNames = new List<StringWithRarity>(newDungeonNames); } } } [CreateAssetMenu(fileName = "LevelMatchingProperties", menuName = "Lethal Level Loader/Utility/LevelMatchingProperties", order = 12)] public class LevelMatchingProperties : MatchingProperties { [Space(5f)] public List<StringWithRarity> levelTags = new List<StringWithRarity>(); [Space(5f)] public List<Vector2WithRarity> currentRoutePrice = new List<Vector2WithRarity>(); [Space(5f)] public List<StringWithRarity> currentWeather = new List<StringWithRarity>(); [Space(5f)] public List<StringWithRarity> planetNames = new List<StringWithRarity>(); public new static LevelMatchingProperties Create(ExtendedContent extendedContent) { LevelMatchingProperties levelMatchingProperties = ScriptableObject.CreateInstance<LevelMatchingProperties>(); ((Object)levelMatchingProperties).name = ((Object)extendedContent).name + "LevelMatchingProperties"; return levelMatchingProperties; } public int GetDynamicRarity(ExtendedLevel extendedLevel) { int currentValue = 0; MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedTags(extendedLevel.ContentTags, levelTags), ((Object)extendedLevel).name, "Content Tags"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedString(extendedLevel.AuthorName, authorNames), ((Object)extendedLevel).name, "Author Name"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedStrings(extendedLevel.ExtendedMod.ModNameAliases, modNames), ((Object)extendedLevel).name, "Mod Name"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingWithinRanges(extendedLevel.RoutePrice, currentRoutePrice), ((Object)extendedLevel).name, "Route Price"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedString(extendedLevel.NumberlessPlanetName, planetNames), ((Object)extendedLevel).name, "Planet Name"); MatchingProperties.UpdateRarity(ref currentValue, MatchingProperties.GetHighestRarityViaMatchingNormalizedString(((object)(LevelWeatherType)(ref extendedLevel.SelectableLevel.currentWeather)).ToString(), currentWeather), ((Object)extendedLevel).name, "Current Weather"); return currentValue; } public void ApplyValues(List<StringWithRarity> newModNames = null, List<StringWithRarity> newAuthorNames = null, List<StringWithRarity> newLevelTags = null, List<Vector2WithRarity> newRoutePrices = null, List<StringWithRarity> newCurrentWeathers = null, List<StringWithRarity> newPlanetNames = null) { if (newModNames != null && newModNames.Count != 0) { modNames = new List<StringWithRarity>(newModNames); } if (newAuthorNames != null && newAuthorNames.Count != 0) { authorNames = new List<StringWithRarity>(newAuthorNames); } if (newLevelTags != null && newLevelTags.Count != 0) { levelTags = new List<StringWithRarity>(newLevelTags); } if (newRoutePrices != null && newRoutePrices.Count != 0) { currentRoutePrice = new List<Vector2WithRarity>(newRoutePrices); } if (newCurrentWeathers != null && newCurrentWeathers.Count != 0) { currentWeather = new List<StringWithRarity>(newCurrentWeathers); } if (newPlanetNames != null && newPlanetNames.Count != 0) { planetNames = new List<StringWithRarity>(newPlanetNames); } } } public class MatchingProperties : ScriptableObject { [Space(5f)] public List<StringWithRarity> modNames = new List<StringWithRarity>(); [Space(5f)] public List<StringWithRarity> authorNames = new List<StringWithRarity>(); public static MatchingProperties Create(ExtendedContent extendedContent) { MatchingProperties matchingProperties = ScriptableObject.CreateInstance<MatchingProperties>(); ((Object)matchingProperties).name = ((Object)extendedContent).name + "MatchingProperties"; return matchingProperties; } internal static bool UpdateRarity(ref int currentValue, int newValue, string debugActionObject = null, string debugActionReason = null) { if (newValue > currentValue) { if (!string.IsNullOrEmpty(debugActionReason)) { if (!string.IsNullOrEmpty(debugActionObject)) { DebugHelper.Log("Raised Rarity Of: " + debugActionObject + " From (" + currentValue + ") To (" + newValue + ") Due To Matching " + debugActionReason, DebugType.Developer); } else { DebugHelper.Log("Raised Rarity From (" + currentValue + ") To (" + newValue + ") Due To Matching " + debugActionReason, DebugType.Developer); } } currentValue = newValue; return true; } return false; } internal static int GetHighestRarityViaMatchingWithinRanges(int comparingValue, List<Vector2WithRarity> matchingVectors) { int num = 0; foreach (Vector2WithRarity matchingVector in matchingVectors) { if (matchingVector.Rarity >= num && (float)comparingValue >= matchingVector.Min && (float)comparingValue <= matchingVector.Max) { num = matchingVector.Rarity; } } return num; } internal static int GetHighestRarityViaMatchingNormalizedString(string comparingString, List<StringWithRarity> matchingStrings) { return GetHighestRarityViaMatchingNormalizedStrings(new List<string> { comparingString }, matchingStrings); } internal static int GetHighestRarityViaMatchingNormalizedTags(List<ContentTag> comparingTags, List<StringWithRarity> matchingStrings) { List<string> comparingStrings = comparingTags.Select((ContentTag t) => t.contentTagName).ToList(); return GetHighestRarityViaMatchingNormalizedStrings(comparingStrings, matchingStrings); } internal static int GetHighestRarityViaMatchingNormalizedStrings(List<string> comparingStrings, List<StringWithRarity> matchingStrings) { int num = 0; foreach (StringWithRarity matchingString in matchingStrings) { foreach (string item in new List<string>(comparingStrings)) { if (matchingString.Rarity >= num && (matchingString.Name.Sanitized().Contains(item.Sanitized()) || item.Sanitized().Contains(matchingString.Name.Sanitized()))) { num = matchingString.Rarity; } } } return num; } } public class MoonsCataloguePage { private List<ExtendedLevelGroup> extendedLevelGroups; public List<ExtendedLevelGroup> ExtendedLevelGroups => extendedLevelGroups; public List<ExtendedLevel> ExtendedLevels { get { List<ExtendedLevel> list = new List<ExtendedLevel>(); foreach (ExtendedLevelGroup extendedLevelGroup in extendedLevelGroups) { foreach (ExtendedLevel extendedLevels in extendedLevelGroup.extendedLevelsList) { list.Add(extendedLevels); } } return list; } } public MoonsCataloguePage(List<ExtendedLevelGroup> newExtendedLevelGroupList) { extendedLevelGroups = new List<ExtendedLevelGroup>(); extendedLevelGroups.Clear(); foreach (ExtendedLevelGroup newExtendedLevelGroup in newExtendedLevelGroupList) { extendedLevelGroups.Add(new ExtendedLevelGroup(newExtendedLevelGroup.extendedLevelsList)); } } public void RebuildLevelGroups(List<ExtendedLevelGroup> newExtendedLevelGroups, int splitCount) { List<ExtendedLevel> list = new List<ExtendedLevel>(); foreach (ExtendedLevelGroup extendedLevelGroup in extendedLevelGroups) { foreach (ExtendedLevel extendedLevels in extendedLevelGroup.extendedLevelsList) { list.Add(extendedLevels); } } RebuildLevelGroups(list.ToArray(), splitCount); } public void RebuildLevelGroups(List<ExtendedLevel> newExtendedLevels, int splitCount) { RebuildLevelGroups(newExtendedLevels.ToArray(), splitCount); } public void RebuildLevelGroups(IOrderedEnumerable<ExtendedLevel> orderedExtendedLevels, int splitCount) { RebuildLevelGroups(orderedExtendedLevels.ToArray(), splitCount); } public void RebuildLevelGroups(ExtendedLevel[] newExtendedLevels, int splitCount) { extendedLevelGroups = TerminalManager.GetExtendedLevelGroups(newExtendedLevels, splitCount); } public void RefreshLevelGroups(List<ExtendedLevelGroup> newLevelGroups) { extendedLevelGroups.Clear(); foreach (ExtendedLevelGroup newLevelGroup in newLevelGroups) { if (newLevelGroup.extendedLevelsList.Count != 0) { extendedLevelGroups.Add(new ExtendedLevelGroup(newLevelGroup.extendedLevelsList)); } } } } [Serializable] public class ExtendedLevelGroup { public List<ExtendedLevel> extendedLevelsList; public int AverageCalculatedDifficulty => GetAverageCalculatedDifficulty(); public ExtendedLevelGroup(List<ExtendedLevel> newExtendedLevelsList) { extendedLevelsList = new List<ExtendedLevel>(newExtendedLevelsList); } public ExtendedLevelGroup(List<SelectableLevel> newSelectableLevelsList) { extendedLevelsList = new List<ExtendedLevel>(); foreach (SelectableLevel newSelectableLevels in newSelectableLevelsList) { extendedLevelsList.Add(LevelManager.GetExtendedLevel(newSelectableLevels)); } } public int GetAverageCalculatedDifficulty() { List<int> list = new List<int>(); foreach (ExtendedLevel extendedLevels in extendedLevelsList) { list.Add(extendedLevels.CalculatedDifficultyRating); } return (int)list.Average(); } } public struct NetworkSceneInfo : INetworkSerializable { public enum SceneOrigin { Build, Bundle } private uint m_levelSceneIndex; private LethalLevelLoaderNetworkManager.StringContainer m_levelScenePath; public string LevelScenePath => m_levelScenePath.SomeText; public int LevelSceneIndex => (int)m_levelSceneIndex; public int SceneIndex { get { NetworkScenePatcher.TryGetSceneIndex((int)m_levelSceneIndex, LevelScenePath, out var sceneIndex); return sceneIndex; } } public bool IsLoaded { get { if (Origin == SceneOrigin.Build) { return true; } if (AssetBundleLoader.TryGetAssetBundleInfo(LevelScenePath, out var info)) { return info.IsLoaded; } return false; } } public SceneOrigin Origin { get { if (SceneIndex >= SceneManager.sceneCountInBuildSettings) { return SceneOrigin.Bundle; } return SceneOrigin.Build; } } public NetworkSceneInfo(int levelSceneIndex, string levelScenePath) { m_levelScenePath = new LethalLevelLoaderNetworkManager.StringContainer(); m_levelScenePath.SomeText = levelScenePath; m_levelSceneIndex = (uint)levelSceneIndex; } public unsafe void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter { //IL_000a: 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) ((BufferSerializer<uint>*)(&serializer))->SerializeValue<uint>(ref m_levelSceneIndex, default(ForPrimitives)); ((BufferSerializer<LethalLevelLoaderNetworkManager.StringContainer>*)(&serializer))->SerializeNetworkSerializable<LethalLevelLoaderNetworkManager.StringContainer>(ref m_levelScenePath); } } public static class PatchedContent { internal static Dictionary<string, ExtendedContent> UniqueIdentifiersDictionary = new Dictionary<string, ExtendedContent>(); internal static Dictionary<SelectableLevel, ExtendedLevel> ExtendedLevelDictionary = new Dictionary<SelectableLevel, ExtendedLevel>(); internal static Dictionary<DungeonFlow, ExtendedDungeonFlow> ExtendedDungeonFlowDictionary = new Dictionary<DungeonFlow, ExtendedDungeonFlow>(); internal static Dictionary<Item, ExtendedItem> ExtendedItemDictionary = new Dictionary<Item, ExtendedItem>(); internal static Dictionary<EnemyType, ExtendedEnemyType> ExtendedEnemyTypeDictionary = new Dictionary<EnemyType, ExtendedEnemyType>(); internal static Dictionary<BuyableVehicle, ExtendedBuyableVehicle> ExtendedBuyableVehicleDictionary = new Dictionary<BuyableVehicle, ExtendedBuyableVehicle>(); internal static Dictionary<UnlockableItem, ExtendedUnlockableItem> ExtendedUnlockableItemDictionary = new Dictionary<UnlockableItem, ExtendedUnlockableItem>(); public static ExtendedMod VanillaMod { get; internal set; } public static List<string> AllLevelSceneNames { get; internal set; } = new List<string>(); public static List<ExtendedMod> ExtendedMods { get; internal set; } = new List<ExtendedMod>(); public static List<ExtendedLevel> ExtendedLevels { get; internal set; } = new List<ExtendedLevel>(); public static List<ExtendedLevel> VanillaExtendedLevels { get { List<ExtendedLevel> list = new List<ExtendedLevel>(); foreach (ExtendedLevel extendedLevel in ExtendedLevels) { if (extendedLevel.ContentType == ContentType.Vanilla) { list.Add(extendedLevel); } } return list; } } public static List<ExtendedLevel> CustomExtendedLevels { get { List<ExtendedLevel> list = new List<ExtendedLevel>(); foreach (ExtendedLevel extendedLevel in ExtendedLevels) { ContentType contentType = extendedLevel.ContentType; if ((contentType == ContentType.Custom || contentType == ContentType.External) ? true : false) { list.Add(extendedLevel); } } return list; } } [Obsolete("Use PatchedContent.SelectableLevels instead.")] public static List<SelectableLevel> SeletectableLevels => SelectableLevels; public static List<SelectableLevel> SelectableLevels { get { List<SelectableLevel> list = new List<SelectableLevel>(); foreach (ExtendedLevel extendedLevel in ExtendedLevels) { list.Add(extendedLevel.SelectableLevel); } return list; } } public static List<SelectableLevel> MoonsCatalogue { get { List<SelectableLevel> list = new List<SelectableLevel>(); foreach (SelectableLevel