Please disclose if your mod was created primarily 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 Enhanced Monsters v1.3.13
BepInEx/plugins/EnhancedMonsters/EnhancedMonsters.dll
Decompiled 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EnhancedMonsters.Config; using EnhancedMonsters.Monobehaviours; using EnhancedMonsters.NetcodePatcher; using EnhancedMonsters.Patches; using EnhancedMonsters.Utils; using GameNetcodeStuff; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalLib.Modules; using LethalSettings.UI; using LethalSettings.UI.Components; using MelanieMeliciousCooked; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyFileVersion("1.3.13")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.13.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnhancedMonsters { [BepInPlugin("com.velddev.enhancedmonsters", "Enhanced Monsters", "1.3.13")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("Entity378.sellbodies")] public class Plugin : BaseUnityPlugin { private static readonly Harmony harmony = new Harmony("com.velddev.enhancedmonsters"); [NotNull] public static ManualLogSource? logger; internal static Plugin Singleton { [return: NotNull] get; private set; } public static GameObject EnemyToPropPrefab { get; private set; } private void Awake() { Singleton = this; logger = ((BaseUnityPlugin)this).Logger; new LocalConfig(((BaseUnityPlugin)this).Config); logger.LogInfo((object)"Local config initialized."); NetcodePatcher(); logger.LogInfo((object)"This is (maybe) NOT an RPG mod. And hi btw."); EnemiesDataManager.LoadEnemiesData(); new SyncedConfig(((BaseUnityPlugin)this).Config); logger.LogInfo((object)"Enemies data loaded and ready to be synchronized."); ApplyAllPatches(); logger.LogDebug((object)"All harmony patches have been applied (energistics)."); CreateThePrefab(); logger.LogDebug((object)"The Prefab have been created correctly"); if ((Object)(object)FastResourcesManager.EnemyScrapIcon == (Object)null) { logger.LogError((object)"EnemyScrapIcon didn't load yet. Caution advised."); } else { logger.LogInfo((object)"EnemyScrapIcon loaded correctly and is ready to use !"); } } private static void ApplyAllPatches() { if (logger == null) { throw new NullReferenceException("logger is null. Cannot process further because it means that the mod was not initialized yet."); } logger.LogDebug((object)"Applying patches..."); harmony.PatchAll(typeof(EnemyAI_Patches)); logger.LogDebug((object)"Enemy patches applied."); logger.LogDebug((object)"MaskedEnemy patches applied."); harmony.PatchAll(typeof(MenuManager_Patches)); logger.LogDebug((object)"MenuManager patches applied."); harmony.PatchAll(typeof(PlayerControllerB_Patches)); logger.LogDebug((object)"PlayerController patches applied."); harmony.PatchAll(typeof(GameNetworkManager_Patches)); logger.LogDebug((object)"GameNetworkManager patches applied."); harmony.PatchAll(typeof(StartOfRound_Patches)); logger.LogDebug((object)"StartOfRound patches applied."); } private static void CreateThePrefab() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) GameObject val = NetworkPrefabs.CreateNetworkPrefab("EnemyAsProp"); val.tag = "PhysicsProp"; val.layer = 6; NetworkObject component = val.GetComponent<NetworkObject>(); component.AutoObjectParentSync = false; component.DontDestroyWithOwner = true; BoxCollider val2 = val.AddComponent<BoxCollider>(); ((Collider)val2).enabled = true; ((Collider)val2).isTrigger = true; val2.size = new Vector3(1.5f, 1.5f, 1.5f); val.AddComponent<EnemyScrap>(); val.AddComponent<AudioSource>(); val.AddComponent<OccludeAudio>(); val.AddComponent<AudioLowPassFilter>(); EnemyToPropPrefab = val; } private static void NetcodePatcher() { Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos; bool flag = pluginInfos.ContainsKey("ainavt.lc.lethalconfig"); bool flag2 = pluginInfos.ContainsKey("com.willis.lc.lethalsettings"); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { bool flag3 = type.FullName.Contains(typeof(LethalConfigSupport).FullName); bool flag4 = type.FullName.Contains(typeof(LethalSettingsSupport).FullName); if ((flag3 && !flag) || (flag4 && !flag2)) { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } } } public static class PluginInfo { public const int ConfigVersion = 11; public const string Version = "1.3.13"; public const string GUID = "com.velddev.enhancedmonsters"; public const string DisplayName = "Enhanced Monsters"; } } namespace EnhancedMonsters.Utils { public static class EnemiesDataManager { [JsonObject] public class EnemyDataFile { public int Version { get; set; } public Dictionary<string, EnemyData> EnemiesData { get; set; } [JsonConstructor] public EnemyDataFile(int version, Dictionary<string, EnemyData> enemiesData) { Version = version; EnemiesData = enemiesData ?? new Dictionary<string, EnemyData>(); base..ctor(); } } public static readonly Dictionary<string, EnemyData> EnemiesData = new Dictionary<string, EnemyData>(); public static readonly Dictionary<string, EnemyData> DefaultEnemiesData = new Dictionary<string, EnemyData> { ["Manticoil"] = new EnemyData(pickupable: true, 10, 20, 12f, "F", new EnemyData.EnemyMetadata(new Vec3(-0.25f, 0.25f, 0.15f), new Vec3(180f, 0f, -90f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)), ["Tulip Snake"] = new EnemyData(pickupable: true, 20, 30, 7f, "F", new EnemyData.EnemyMetadata(new Vec3(-0.15f, 0.1f, 0.11f), new Vec3(0f, 90f, 90f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)), ["Hoarding bug"] = new EnemyData(pickupable: true, 55, 90, 50f, "E", new EnemyData.EnemyMetadata(new Vec3(0.1f, 0.2f, -0.3f), new Vec3(0f, 0f, 90f), new Vec3(0f, 0f, 0f))), ["Puffer"] = new EnemyData(pickupable: true, 30, 60, 69f, "E", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))), ["Centipede"] = new EnemyData(pickupable: true, 45, 70, 35f, "D", new EnemyData.EnemyMetadata(new Vec3(-0.25f, 0.1f, 0f), new Vec3(0f, 0f, -90f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)), ["Baboon hawk"] = new EnemyData(pickupable: true, 75, 100, 105f, "D", new EnemyData.EnemyMetadata(new Vec3(-0.3f, 0.5f, 1.5f), new Vec3(0f, 0f, 90f), new Vec3(0f, 0f, 0f))), ["Bunker Spider"] = new EnemyData(pickupable: true, 70, 110, 75f, "C", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))), ["MouthDog"] = new EnemyData(pickupable: true, 175, 250, 250f, "C", new EnemyData.EnemyMetadata(new Vec3(-1.25f, -1f, -0.5f), new Vec3(180f, 0f, -90f), new Vec3(180f, 0f, 180f))), ["Crawler"] = new EnemyData(pickupable: true, 120, 160, 100f, "B", new EnemyData.EnemyMetadata(new Vec3(-0.5f, 0f, -1f), new Vec3(0f, 0f, -60f), new Vec3(0f, 0f, 0f))), ["Flowerman"] = new EnemyData(pickupable: true, 160, 190, 40f, "B", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 1.5f), new Vec3(0f, 90f, -90f), new Vec3(-90f, 0f, 0f), animateOnDeath: false)), ["Butler"] = new EnemyData(pickupable: true, 170, 199, 77f, "B", new EnemyData.EnemyMetadata(new Vec3(-0.5f, 0f, 1f), new Vec3(0f, 90f, -90f), new Vec3(-90f, 0f, 0f), animateOnDeath: false)), ["Nutcracker"] = new EnemyData(pickupable: true, 190, 220, 43f, "A", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 1.5f), new Vec3(0f, 90f, -90f), new Vec3(-90f, 0f, 0f), animateOnDeath: false)), ["Maneater"] = new EnemyData(pickupable: true, 250, 290, 42f, "S", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), animateOnDeath: true, twoHanded: false)), ["Docile Locust Bees"] = new EnemyData(pickupable: false, 0, 0, 0f, "F", new EnemyData.EnemyMetadata()), ["Red pill"] = new EnemyData(pickupable: false, 0, 0, 0f, "F", new EnemyData.EnemyMetadata()), ["Blob"] = new EnemyData(pickupable: false, 0, 0, 0f, "D", new EnemyData.EnemyMetadata()), ["Red Locust Bees"] = new EnemyData(pickupable: false, 0, 0, 0f, "C", new EnemyData.EnemyMetadata()), ["Butler Bees"] = new EnemyData(pickupable: false, 0, 0, 0f, "C", new EnemyData.EnemyMetadata()), ["Earth Leviathan"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()), ["Masked"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()), ["Clay Surgeon"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()), ["Spring"] = new EnemyData(pickupable: false, 0, 0, 0f, "A", new EnemyData.EnemyMetadata()), ["Jester"] = new EnemyData(pickupable: false, 0, 0, 0f, "S+", new EnemyData.EnemyMetadata()), ["RadMech"] = new EnemyData(pickupable: false, 0, 0, 0f, "S+", new EnemyData.EnemyMetadata()), ["Girl"] = new EnemyData(pickupable: false, 0, 0, 0f, "?", new EnemyData.EnemyMetadata()), ["Lasso"] = new EnemyData(pickupable: false, 0, 0, 0f, "dont exist haha", new EnemyData.EnemyMetadata()), ["ForestGiant"] = new EnemyData(pickupable: false, 0, 0, 0f, "S", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 90f, 0f), new Vec3(90f, 0f, 0f), animateOnDeath: false)), ["PinkGiant"] = new EnemyData(pickupable: false, 0, 0, 0f, "F", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 90f, 0f), new Vec3(0f, 0f, 0f), animateOnDeath: false)), ["Football"] = new EnemyData(pickupable: false, 0, 0, 0f, "B", new EnemyData.EnemyMetadata()), ["Locker"] = new EnemyData(pickupable: false, 0, 0, 0f, "A", new EnemyData.EnemyMetadata()), ["Bush Wolf"] = new EnemyData(pickupable: true, 250, 320, 51f, "A", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))), ["PjonkGoose"] = new EnemyData(pickupable: true, 279, 340, 64f, "A", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f))) }; public static string EnemiesDataFile = Path.Combine(Paths.ConfigPath, "EnhancedMonsters", "EnemiesData.json"); public static readonly Dictionary<string, GameObject> Enemies2Props = new Dictionary<string, GameObject>(); public static readonly List<Item> AllEnemiesScraps = new List<Item>(); public static void LoadEnemiesData() { if (!File.Exists(EnemiesDataFile)) { Plugin.logger.LogWarning((object)"Enemy Data File did not exist!"); EnemiesData.ProperConcat(DefaultEnemiesData); SaveEnemiesData(); return; } string text = File.ReadAllText(EnemiesDataFile); Plugin.logger.LogDebug((object)text); EnemyDataFile enemyDataFile = JsonConvert.DeserializeObject<EnemyDataFile>(text); if (enemyDataFile == null) { Plugin.logger.LogWarning((object)"Enemy Data File seems to be empty or invalid."); EnemiesData.ProperConcat(DefaultEnemiesData); SaveEnemiesData(); } else if (checked(11 - enemyDataFile.Version) > 1) { Plugin.logger.LogWarning((object)"Enemy Data File seems to be outdated. A new config file will be created."); EnemiesData.ProperConcat(DefaultEnemiesData); string text2 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "..", "config", "EnhancedMonsters", "OLD_EnemiesData.json"); if (File.Exists(text2)) { File.Delete(text2); } File.Move(EnemiesDataFile, text2); SaveEnemiesData(); } else { EnemiesData.ProperConcat(enemyDataFile.EnemiesData); Plugin.logger.LogDebug((object)$"{enemyDataFile} => {EnemiesData.Count}"); EnemiesData.ProperConcat(DefaultEnemiesData); Plugin.logger.LogDebug((object)$"{DefaultEnemiesData.Count} => {EnemiesData.Count}"); SaveEnemiesData(); } } public static void RegisterEnemy(string enemyName, bool sellable, int minPrice, int maxPrice, float mass, string rank, EnemyData.EnemyMetadata metadata, bool overrideRegister = false) { if (!EnemiesData.ContainsKey(enemyName)) { EnemiesData.Add(enemyName, new EnemyData(sellable, minPrice, maxPrice, mass, rank, metadata)); } else { if (!overrideRegister) { string name = Assembly.GetCallingAssembly().GetName().Name; Plugin.logger.LogWarning((object)("Cannot register modded from mod " + name + " enemy " + enemyName + ": It is already registered (either from file or from .")); return; } EnemiesData[enemyName] = new EnemyData(sellable, minPrice, maxPrice, mass, rank, metadata); } if (Synchronizable<SyncedConfig>.Instance == null || Synchronizable<SyncedConfig>.IsHost || !NetworkManager.Singleton.IsListening) { SyncedConfig.BroadcastSync(); } } internal static void RegisterEnemy(string enemyName, EnemyData enemyData) { if (Synchronizable<SyncedConfig>.IsHost || !NetworkManager.Singleton.IsListening) { if (EnemiesData != Synchronizable<SyncedConfig>.Instance.EnemiesData) { Plugin.logger.LogError((object)"Cannot update the mob configs. Somehow, the EnemiesData from the EnemiesDataManager and the one from the SyncedConfigs are not the same, even though they both are yours."); } else if (!EnemiesData.TryAdd(enemyName, enemyData)) { Plugin.logger.LogDebug((object)("EnemyData '" + enemyName + "' already exists!")); } else { SyncedConfig.BroadcastSync(); } } } public static void SaveEnemiesData() { if (!Synchronizable<SyncedConfig>.IsHost) { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsListening) { return; } } EnemyDataFile enemyDataFile = new EnemyDataFile(11, EnemiesData); string contents = JsonConvert.SerializeObject((object)enemyDataFile, (Formatting)1); if (!Directory.Exists(Path.GetDirectoryName(EnemiesDataFile))) { Directory.CreateDirectory(Path.GetDirectoryName(EnemiesDataFile)); } File.WriteAllText(EnemiesDataFile, contents); Plugin.logger.LogInfo((object)"Saved enemies data."); } public static void EnsureEnemy2PropPrefabs() { //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0577: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Unknown result type (might be due to invalid IL or missing references) EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>(); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if ((Object)(object)val.enemyType == (Object)null) { Plugin.logger.LogWarning((object)("Entity " + ((Object)val).name + " have been skipped: This entity lacks an EnemyType !")); continue; } Plugin.logger.LogInfo((object)("Registering NetworkPrefab '" + val.enemyType.enemyName + "'")); ref string enemyName = ref val.enemyType.enemyName; if (Enemies2Props.TryGetValue(val.enemyType.enemyName, out GameObject value)) { if (!Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].Pickupable) { Enemies2Props.Remove(enemyName); continue; } EnemyScrap component = value.GetComponent<EnemyScrap>(); component.enemyType = val.enemyType; ((GrabbableObject)component).itemProperties.minValue = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].MinValue; ((GrabbableObject)component).itemProperties.maxValue = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].MaxValue; ((GrabbableObject)component).itemProperties.weight = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].LCMass; } else { if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.TryGetValue(enemyName, out var value2) || !value2.Pickupable) { continue; } GameObject val2 = new GameObject(((Object)val).name + " neutralized"); foreach (Transform item in ((Component)val).transform) { Transform val3 = item; if (!((Object)val3).name.StartsWith("MapDot") && !((Object)val3).name.StartsWith("Collider") && !((Object)val3).name.StartsWith("VoiceSFX") && !((Object)val3).name.StartsWith("CreatureSFX") && !((Object)val3).name.StartsWith("SeepingSFX") && !((Object)val3).name.StartsWith("CreatureVoice") && !((Object)val3).name.StartsWith("Ambience")) { Transform val4 = Object.Instantiate<Transform>(val3); ((Object)val4).name = ((Object)val3).name; ((Component)val4).transform.parent = val2.transform; } } val2.RemoveComponentsInChildren<Collider>(); val2.RemoveComponentsInChildren<AudioLowPassFilter>(); val2.RemoveComponentsInChildren<AudioReverbFilter>(); val2.RemoveComponentsInChildren<OccludeAudio>(); val2.RemoveComponentsInChildren<EnemyAICollisionDetect>(); val2.RemoveComponentsInChildren<AudioSource>(); val2.RemoveComponentsInChildren<ParticleSystem>(); val2.RemoveComponentsInChildren<ParticleSystemRenderer>(); val2.transform.localScale = ((Component)val).transform.localScale; GameObject val5 = NetworkPrefabs.CloneNetworkPrefab(Plugin.EnemyToPropPrefab, "Dead " + ((Object)val).name); val2.transform.parent = val5.transform; Plugin.logger.LogInfo((object)("Attached " + ((Object)val2).name + " to " + ((Object)val2.transform.parent).name)); EnemyScrap component2 = val5.GetComponent<EnemyScrap>(); component2.EnemyGameObject = val2; CleanEnemyObj(component2.EnemyGameObject); Plugin.logger.LogInfo((object)"Set EnemyGameObject on EnemyScrap."); ((GrabbableObject)component2).grabbable = true; ((GrabbableObject)component2).grabbableToEnemies = false; component2.enemyType = val.enemyType; BoxCollider component3 = val5.GetComponent<BoxCollider>(); component3.size = value2.Metadata.CollisionExtents; ScanNodeProperties componentInChildren = val2.GetComponentInChildren<ScanNodeProperties>(); if (!Object.op_Implicit((Object)(object)componentInChildren)) { Object.Destroy((Object)(object)val5); continue; } Transform transform = ((Component)componentInChildren).gameObject.transform; ((Component)transform).transform.parent = val5.transform; ((Component)transform).gameObject.AddComponent<BoxCollider>(); transform.localPosition = new Vector3(0f, 0f, 0f); componentInChildren.maxRange = 13; componentInChildren.minRange = 1; componentInChildren.nodeType = 2; componentInChildren.requiresLineOfSight = true; componentInChildren.headerText = "Dead " + componentInChildren.headerText; Item val6 = (((GrabbableObject)component2).itemProperties = ScriptableObject.CreateInstance<Item>()); ((Object)val6).name = enemyName + " scrap"; val6.itemName = componentInChildren.headerText; val6.saveItemVariable = true; val6.itemIcon = FastResourcesManager.EnemyScrapIcon; val6.minValue = value2.MinValue; val6.maxValue = value2.MaxValue; val6.allowDroppingAheadOfPlayer = true; val6.canBeGrabbedBeforeGameStart = true; val6.isScrap = true; val6.itemSpawnsOnGround = false; val6.twoHanded = value2.Metadata.TwoHanded; val6.requiresBattery = false; val6.twoHandedAnimation = value2.Metadata.TwoHanded; val6.weight = value2.LCMass; val6.spawnPrefab = val5; val6.restingRotation = value2.Metadata.FloorRotation; val6.rotationOffset = value2.Metadata.HandRotation; val6.positionOffset = value2.Metadata.MeshOffset; EnemyData enemyData = Synchronizable<SyncedConfig>.Default.EnemiesData[enemyName]; AudioClip value3; if (enemyData.Metadata.DropSFX == "default") { val6.dropSFX = FastResourcesManager.EnemyDropDefaultSound; } else if (FastResourcesManager.CustomAudioClips.TryGetValue(enemyData.Metadata.DropSFX, out value3)) { val6.dropSFX = value3; } else { val6.dropSFX = null; } AudioClip value4; if (enemyData.Metadata.GrabSFX == "default") { val6.grabSFX = FastResourcesManager.EnemyDropDefaultSound; } else if (FastResourcesManager.CustomAudioClips.TryGetValue(enemyData.Metadata.GrabSFX, out value4)) { val6.grabSFX = value4; } else { val6.grabSFX = null; } AudioClip value5; if (enemyData.Metadata.PocketSFX == "default") { val6.pocketSFX = FastResourcesManager.EnemyDropDefaultSound; } else if (FastResourcesManager.CustomAudioClips.TryGetValue(enemyData.Metadata.PocketSFX, out value5)) { val6.pocketSFX = value5; } else { val6.pocketSFX = null; } Items.RegisterItem(val6); Items.RegisterScrap(val6, 0, (LevelTypes)1); AllEnemiesScraps.Add(val6); Enemies2Props.Add(enemyName, val5); Plugin.logger.LogInfo((object)("Registered NetworkPrefab '" + ((Object)val5).name + "'/'" + ((Object)val2).name + "' (" + val6.itemName + ")")); } } if (FarmingAndCookingSupport.FarmingAndCookingLoaded) { FarmingAndCookingSupport.RegisterFarmingAndCookingBodies(AllEnemiesScraps); } } public static void CleanEnemyObj(GameObject enemyObj) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown try { if (((Object)enemyObj).name.Contains("SandSpider")) { return; } int num = (Object.op_Implicit((Object)(object)Camera.main) ? Camera.main.cullingMask : 591075327); Renderer[] componentsInChildren = enemyObj.GetComponentsInChildren<Renderer>(true); Animator component = enemyObj.GetComponent<Animator>(); if ((Object)(object)component != (Object)null) { component.Update(0f); } Plugin.logger.LogInfo((object)("Starting cleanup on '" + ((Object)enemyObj).name + "'")); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null)) { bool enabled = val.enabled; bool flag = ((1 << ((Component)val).gameObject.layer) & num) != 0; if (!enabled || !flag) { Plugin.logger.LogInfo((object)("Removing renderer '" + ((Object)val).name + "' from '" + ((Object)enemyObj).name + "'")); Object.DestroyImmediate((Object)(object)val); } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if (val2 != null) { Mesh val3 = new Mesh(); val2.BakeMesh(val3); } } } Plugin.logger.LogInfo((object)("Cleanup completed on '" + ((Object)enemyObj).name + "'")); } catch (Exception arg) { Plugin.logger.LogError((object)$"ERROR cleaning '{((Object)enemyObj).name}': {arg}"); } } } [Serializable] [JsonObject(Description = "The value of a mob once killed, if it can be killed.")] public record struct EnemyData { [Serializable] [JsonObject(Description = "The metadata of a mob once killed, if it can be killed.")] public record struct EnemyMetadata { public Vec3 MeshOffset; public Vec3 HandRotation; public Vec3 FloorRotation; public Vec3 CollisionExtents; public bool AnimateOnDeath; public bool TwoHanded; public string DropSFX; public string GrabSFX; public string PocketSFX; public Dictionary<string, float> LootTable; [JsonConstructor] public EnemyMetadata() { DropSFX = "default"; GrabSFX = "none"; PocketSFX = "none"; MeshOffset = default(Vec3); HandRotation = default(Vec3); FloorRotation = default(Vec3); CollisionExtents = new Vec3(1.5f, 1.5f, 1.5f); AnimateOnDeath = false; TwoHanded = true; DropSFX = "default"; GrabSFX = "none"; PocketSFX = "none"; LootTable = new Dictionary<string, float>(); } public EnemyMetadata(Vec3 meshOffset = default(Vec3), Vec3 handRotation = default(Vec3), Vec3 floorRotation = default(Vec3), bool animateOnDeath = true, bool twoHanded = true, Dictionary<string, float>? loots = null, string dropsfx = "default", string grabsfx = "none", string pocketsfx = "none", Vec3? collisionSize = null) { DropSFX = "default"; GrabSFX = "none"; PocketSFX = "none"; MeshOffset = meshOffset; HandRotation = handRotation; FloorRotation = floorRotation; CollisionExtents = collisionSize ?? new Vec3(1.5f, 1.5f, 1.5f); AnimateOnDeath = animateOnDeath; TwoHanded = twoHanded; DropSFX = dropsfx; GrabSFX = grabsfx; PocketSFX = pocketsfx; LootTable = loots ?? new Dictionary<string, float>(); } } [JsonIgnore] public readonly float LCMass => Mass / 105f + 1f; public bool Pickupable; public int MinValue; public int MaxValue; public float Mass; public string Rank; public EnemyMetadata Metadata; [JsonConstructor] public EnemyData() { Pickupable = true; MinValue = 80; MaxValue = 110; Mass = 50f; Rank = "C"; Metadata = new EnemyMetadata(); } public EnemyData(bool pickupable = true, int minValue = 80, int maxValue = 250, float mass = 50f, string rank = "E", EnemyMetadata? metadata = null) { Pickupable = pickupable; MinValue = minValue; MaxValue = maxValue; Mass = mass; Rank = rank; Metadata = metadata ?? new EnemyMetadata(); } [CompilerGenerated] private readonly bool PrintMembers(StringBuilder builder) { builder.Append("Pickupable = "); builder.Append(Pickupable.ToString()); builder.Append(", MinValue = "); builder.Append(MinValue.ToString()); builder.Append(", MaxValue = "); builder.Append(MaxValue.ToString()); builder.Append(", Mass = "); builder.Append(Mass.ToString()); builder.Append(", Rank = "); builder.Append((object?)Rank); builder.Append(", Metadata = "); builder.Append(Metadata.ToString()); builder.Append(", LCMass = "); builder.Append(LCMass.ToString()); return true; } } [Serializable] [JsonObject(Description = "A simple and flexible Vector3 structure.")] public record struct Vec3 { public float X; public float Y; public float Z; [JsonConstructor] public Vec3(float x, float y, float z) { Z = 0f; X = x; Y = y; Z = z; } public static implicit operator Vector3(Vec3 v) { return new Vector3(v.X, v.Y, v.Z); } public static implicit operator Vector3(Vec3 v) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.X, v.Y, v.Z); } public static implicit operator Vec3(Vector3 v) { return new Vec3(v.X, v.Y, v.Z); } public static implicit operator Vec3(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vec3(v.x, v.y, v.z); } public static Vec3 operator *(Vec3 l, float r) { return new Vec3(l.X * r, l.Y * r, l.Z * r); } public static Vec3 operator *(Vec3 l, Vec3 r) { return new Vec3(l.X * r.X, l.Y * r.Y, l.Z * r.Z); } public static Vec3 operator /(Vec3 l, float r) { return new Vec3(l.X / r, l.Y / r, l.Z / r); } public static Vec3 operator /(Vec3 l, Vec3 r) { return new Vec3(l.X / r.X, l.Y / r.Y, l.Z / r.Z); } public static Vec3 operator +(Vec3 l, Vec3 r) { return new Vec3(l.X + r.X, l.Y + r.Y, l.Z + r.Z); } public static Vec3 operator -(Vec3 l, Vec3 r) { return new Vec3(l.X - r.X, l.Y - r.Y, l.Z - r.Z); } public static Vec3 operator -(Vec3 s) { return new Vec3(0f - s.X, 0f - s.Y, 0f - s.Z); } public static float operator ~(Vec3 l) { return l.Length(); } public readonly float Length() { return (float)Math.Sqrt(Math.Pow(X, 2.0) + Math.Pow(Y, 2.0) + Math.Pow(Z, 2.0)); } public readonly void Deconstruct(out float x, out float y, out float z) { x = X; y = Y; z = Z; } public readonly void Deconstruct(out float x, out float y) { x = X; y = Y; } } internal static class FarmingAndCookingSupport { private static bool? farmingAndCookingLoaded; public static bool FarmingAndCookingLoaded { get { bool valueOrDefault = farmingAndCookingLoaded.GetValueOrDefault(); if (!farmingAndCookingLoaded.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("MelanieMelicious.FarmAndCook"); farmingAndCookingLoaded = valueOrDefault; } return farmingAndCookingLoaded.Value; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void RegisterFarmingAndCookingBodies(List<Item> bodies) { foreach (Item body in bodies) { Plugin.bodyHash.Add(body); Plugin.logger.LogDebug((object)("Registered " + body.itemName + " for MelanieMeliciousCooked plugin.")); } Plugin.logger.LogInfo((object)"Successfully registered all the corpses as grindable for the Farming & Cooking mod."); } } internal static class FastResourcesManager { public static AssetBundle Resources; public static readonly Dictionary<string, AudioClip> CustomAudioClips; public static Sprite EnemyScrapIcon { get; private set; } public static AudioClip EnemyDropDefaultSound { get; private set; } public static string CustomSoundsFolder => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "..", "configs", "EnhancedMonsters", "CustomSFX"); static FastResourcesManager() { CustomAudioClips = new Dictionary<string, AudioClip>(); string name = Assembly.GetExecutingAssembly().GetManifestResourceNames()[0]; Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name); Resources = AssetBundle.LoadFromStream(manifestResourceStream); EnemyScrapIcon = Resources.LoadAsset<Sprite>("EnemyScrapItemIcon"); EnemyDropDefaultSound = Resources.LoadAsset<AudioClip>("BodyDrop"); } private static void LoadCustomSounds() { if (!Directory.Exists(CustomSoundsFolder)) { Directory.CreateDirectory(CustomSoundsFolder); Plugin.logger.LogInfo((object)"CustomSFX folder didn't exist, created one."); } string[] files = Directory.GetFiles(CustomSoundsFolder, "*.ogg", SearchOption.TopDirectoryOnly); string[] array = files; checked { foreach (string path in array) { string soundName = Path.GetFileNameWithoutExtension(path); if (CustomAudioClips.ContainsKey(soundName)) { soundName += CustomAudioClips.Keys.Where((string n) => n == soundName).Count(); } AudioClip val = AudioClip.Create("EM_CSFX_" + soundName, 88200, 1, 44100, false); FileStream fileStream = new FileStream(path, FileMode.Open); float[] array2 = new float[(int)unchecked(fileStream.Length / 4)]; for (int j = 0; j < fileStream.Length; j += 4) { Span<byte> span = stackalloc byte[4]; fileStream.Read(span); array2[unchecked(j / 4)] = BitConverter.ToSingle(span); } fileStream.Dispose(); val.SetData(array2.ToArray(), 0); CustomAudioClips.Add(soundName, val); } } } } public static class Utility { public const float KgToLb = 2.2046227f; public static string ToStringObj(this object obj, string prefix = "") { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(prefix + obj.GetType().FullName + ": {"); FieldInfo[] fields = obj.GetType().GetFields(); foreach (FieldInfo fieldInfo in fields) { object arg = fieldInfo.GetValue(obj) ?? null; stringBuilder.AppendLine(prefix + $"\t{fieldInfo.FieldType.Name} {fieldInfo.Name}: {arg}"); } stringBuilder.AppendLine(prefix + "}"); return stringBuilder.ToString(); } public static T EnsureComponent<T>(this GameObject go) where T : Component { if (go == null) { throw new NullReferenceException("The gameObject is a null reference."); } T result = default(T); if (!go.TryGetComponent<T>(ref result)) { return go.AddComponent<T>(); } return result; } public static void AddRange<K, T, TI>(this IDictionary<K, T> target, IEnumerable<TI> source, Func<TI, K> key, Func<TI, T> selector, bool set = true) { foreach (TI item in source) { K key2 = key(item); T value = selector(item); if (set) { target[key2] = value; } else { target.TryAdd(key(item), selector(item)); } } } public static void ProperConcat<K, T>(this IDictionary<K, T> target, IDictionary<K, T> source) { foreach (KeyValuePair<K, T> item in source) { if (!target.ContainsKey(item.Key)) { target.Add(item.Key, item.Value); } } } public static void RemoveComponentsInChildren<T>(this GameObject go) where T : Component { T[] componentsInChildren = go.GetComponentsInChildren<T>(); T[] array = componentsInChildren; foreach (T val in array) { Plugin.logger.LogDebug((object)("Destroying component " + ((object)val).GetType().Name + " on " + ((Object)(object)val).name + " (child of " + ((Object)go).name + ")")); Object.Destroy((Object)(object)val); } } internal static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) { if (assembly == null) { throw new ArgumentNullException("assembly"); } try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type t) => t != null); } } public static Vector3 ToUnityVec(this Vector3 v) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.X, v.Y, v.Z); } public static Vector3 ToSystemVec(this Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.x, v.y, v.z); } } } namespace EnhancedMonsters.Patches { [HarmonyPatch(typeof(EnemyAI))] public class EnemyAI_Patches { [HarmonyPrefix] [HarmonyPatch(typeof(EnemyAI), "Start")] private static void Start(EnemyAI __instance) { if (__instance.enemyType == null) { return; } SyncedConfig syncedConfig = (LocalConfig.Singleton.synchronizeRanks.Value ? Synchronizable<SyncedConfig>.Instance : Synchronizable<SyncedConfig>.Default); if (!syncedConfig.EnemiesData.TryGetValue(__instance.enemyType.enemyName, out var value)) { Plugin.logger.LogWarning((object)("Enemy " + __instance.enemyType.enemyName + " is not registered in the enemies data. Registering it now.")); value = new EnemyData(pickupable: true, 80, 250, 50f, "E", null); EnemiesDataManager.RegisterEnemy(__instance.enemyType.enemyName, value); } if (!(value.Rank == string.Empty)) { string rank = value.Rank; ScanNodeProperties componentInChildren = ((Component)__instance).gameObject.GetComponentInChildren<ScanNodeProperties>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.subText = "Rank " + rank; } } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "KillEnemy")] private static void KillEnemy(EnemyAI __instance, bool destroy) { //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.enemyType == (Object)null) { return; } Plugin.logger.LogDebug((object)("Mob " + __instance.enemyType.enemyName + " died.")); if (destroy) { return; } if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(__instance.enemyType.enemyName)) { EnemiesDataManager.RegisterEnemy(__instance.enemyType.enemyName, new EnemyData(pickupable: true, 80, 250, 50f, "E", null)); Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + __instance.enemyType.enemyName + "'")); } if (NetworkManager.Singleton.IsServer) { Plugin.logger.LogDebug((object)("Spawning EnemyScrap for enemy " + __instance.enemyType.enemyName + ".")); if (!EnemiesDataManager.Enemies2Props.TryGetValue(__instance.enemyType.enemyName, out GameObject value)) { Plugin.logger.LogWarning((object)("Mob " + __instance.enemyType.enemyName + " has no enemy2prop prefab.")); return; } GameObject val = Object.Instantiate<GameObject>(value); ((Object)val).hideFlags = (HideFlags)0; val.transform.position = ((Component)__instance).transform.position; val.GetComponent<NetworkObject>().Spawn(false); ((Component)__instance).transform.position = new Vector3(-10000f, -10000f, -10000f); __instance.SyncPositionToClients(); } Plugin.logger.LogDebug((object)"Mob should now be grabbable for all users."); } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManager_Patches { [HarmonyPostfix] [HarmonyPatch("StartDisconnect")] public static void StartDisconnect() { Synchronizable<SyncedConfig>.RevertSync(); } [HarmonyPostfix] [HarmonyPatch("SaveItemsInShip")] public static void SaveItemsInShip(GameNetworkManager __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) GrabbableObject[] array = Object.FindObjectsByType<GrabbableObject>((FindObjectsInactive)0, (FindObjectsSortMode)0); Bounds bounds = StartOfRound.Instance.shipBounds.bounds; Vector3 center = ((Bounds)(ref bounds)).center; bounds = StartOfRound.Instance.shipBounds.bounds; Physics.OverlapBox(center, ((Bounds)(ref bounds)).size / 2f, ((Component)StartOfRound.Instance.shipBounds).transform.rotation, 6, (QueryTriggerInteraction)2); for (int i = 0; i < array.Length && i <= StartOfRound.Instance.maxShipItemCapacity; i = checked(i + 1)) { GrabbableObject val = array[i]; Plugin.logger.LogInfo((object)("SAVE CHECKER: Checking object " + val.itemProperties.itemName + "...")); if (StartOfRound.Instance.allItemsList.itemsList.Contains(val.itemProperties) && !val.deactivated) { if ((Object)(object)val.itemProperties.spawnPrefab == (Object)null) { Plugin.logger.LogError((object)("SAVE CHECKER: Object " + val.itemProperties.itemName + " didn't have a spawn prefab.")); continue; } if (val.itemUsedUp) { Plugin.logger.LogError((object)("SAVE CHECKER: Object " + val.itemProperties.itemName + " didn't save because it was used up.")); continue; } if (val.itemProperties.isScrap) { Plugin.logger.LogInfo((object)$"SAVE CHECKER: Saving object {val.itemProperties.itemName} scrap value: ${val.scrapValue}"); } Plugin.logger.LogInfo((object)("SAVE CHECKER: Saving object " + val.itemProperties.itemName)); } else { Plugin.logger.LogInfo((object)$"SAVE CHECKER: Not saving {val.itemProperties.itemName}. Deactivated: {val.deactivated} - Registered correctly: {StartOfRound.Instance.allItemsList.itemsList.Contains(val.itemProperties)}"); } } } } [HarmonyPatch(typeof(MaskedPlayerEnemy))] public class MaskedPlayerEnemy_Patches { [HarmonyPostfix] [HarmonyPatch(typeof(MaskedPlayerEnemy), "KillEnemyServerRpc")] private static void KillEnemyServerRpc(MaskedPlayerEnemy __instance, bool destroy) { Plugin.logger.LogInfo((object)"Hey. Spawn a mimic mask. now."); } } [HarmonyPatch(typeof(MenuManager))] public class MenuManager_Patches { [HarmonyPostfix] [HarmonyPatch(typeof(MenuManager), "Start")] private static void Start(MenuManager __instance) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)__instance)) { Plugin.logger.LogError((object)"MenuManager instance is null. Something might have booted too early."); return; } if (__instance.versionNumberText == null) { Plugin.logger.LogWarning((object)"It seems like the Version Number Text of main menu is missing, it's probably the first main menu iteration. Skipping this one."); return; } TextMeshProUGUI versionNumberText = __instance.versionNumberText; ((TMP_Text)versionNumberText).text = ((TMP_Text)versionNumberText).text + "\n<size=75%>Enhanced Monsters v1.3.13</size>"; ((Component)__instance.versionNumberText).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(500f, 50f); EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>(); Plugin.logger.LogInfo((object)$"{array.Length} enemies to patch."); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (val == null) { Plugin.logger.LogWarning((object)"An enemy is null!"); } else if (val.enemyType == null) { Plugin.logger.LogWarning((object)(((Object)val).name + " has a null enemyType (tf?)")); } else if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName)) { EnemiesDataManager.RegisterEnemy(val.enemyType.enemyName, new EnemyData(pickupable: true, 80, 250, 50f, "E", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f)))); Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + val.enemyType.enemyName + "'")); } } EnemiesDataManager.SaveEnemiesData(); EnemiesDataManager.EnsureEnemy2PropPrefabs(); Plugin.logger.LogInfo((object)"All enemies have been patched correctly."); } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerB_Patches { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnReceiveSync; } [HarmonyPrefix] [HarmonyPatch("ConnectClientToPlayerObject")] public static void InitializeLocalPlayerPrefabs() { EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>(); Plugin.logger.LogInfo((object)$"Double checking {array.Length} enemies. The list may have changed."); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName)) { EnemiesDataManager.RegisterEnemy(val.enemyType.enemyName, new EnemyData(pickupable: true, 80, 250, 50f, "E", new EnemyData.EnemyMetadata(new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f), new Vec3(0f, 0f, 0f)))); Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + val.enemyType.enemyName + "'")); } } EnemiesDataManager.SaveEnemiesData(); EnemiesDataManager.EnsureEnemy2PropPrefabs(); } [HarmonyPostfix] [HarmonyPatch("ConnectClientToPlayerObject")] public static void InitializeLocalPlayer() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (Synchronizable<SyncedConfig>.IsHost) { CustomMessagingManager messagingManager = Synchronizable<SyncedConfig>.MessagingManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = SyncedConfig.OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } messagingManager.RegisterNamedMessageHandler("EnhancedMonsters_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); Synchronizable<SyncedConfig>.Synced = true; return; } Synchronizable<SyncedConfig>.Synced = false; CustomMessagingManager messagingManager2 = Synchronizable<SyncedConfig>.MessagingManager; object obj2 = <>O.<1>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = SyncedConfig.OnReceiveSync; <>O.<1>__OnReceiveSync = val2; obj2 = (object)val2; } messagingManager2.RegisterNamedMessageHandler("EnhancedMonsters_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2); SyncedConfig.RequestSync(); } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRound_Patches { [HarmonyPostfix] [HarmonyPatch("Start")] public static void StartPatch() { EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>(); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (val == null) { Plugin.logger.LogWarning((object)"An enemy is null!"); } else if (val.enemyType == null) { Plugin.logger.LogWarning((object)(((Object)val).name + " has a null enemyType (tf?)")); } else if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName)) { EnemiesDataManager.RegisterEnemy(val.enemyType.enemyName, new EnemyData()); Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + val.enemyType.enemyName + "'")); } } EnemiesDataManager.SaveEnemiesData(); EnemiesDataManager.EnsureEnemy2PropPrefabs(); } } } namespace EnhancedMonsters.Monobehaviours { public class EnemyScrap : GrabbableObject { [CompilerGenerated] private sealed class <DisableAnimatorOnAnimationEnd>d__30 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemyScrap <>4__this; private AnimatorClipInfo[] <currentClip>5__1; private float <deathAnimDuration>5__2; private float <deathAnimProgress>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DisableAnimatorOnAnimationEnd>d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <currentClip>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <currentClip>5__1 = <>4__this.EnemyAnimator.GetCurrentAnimatorClipInfo(0); if (<currentClip>5__1.Length < 1) { return false; } <deathAnimDuration>5__2 = ((AnimatorClipInfo)(ref <currentClip>5__1[0])).clip.length; AnimatorStateInfo currentAnimatorStateInfo = <>4__this.EnemyAnimator.GetCurrentAnimatorStateInfo(0); <deathAnimProgress>5__3 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime; break; } case 1: <>1__state = -1; break; } if (<deathAnimProgress>5__3 < <deathAnimDuration>5__2) { <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; } ((Behaviour)<>4__this.EnemyAnimator).enabled = false; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public EnemyType enemyType; private readonly NetworkVariable<int> _syncedScrapValue = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); private const string SpiderSafeTag = "ShowArachnophobeMesh"; public Animator EnemyAnimator { get; private set; } public ScanNodeProperties ScanNode { get; private set; } public GameObject EnemyGameObject { get; set; } public EnemyData EnemyData => LocalConfig.Singleton.synchronizeRanks.Value ? Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyType.enemyName] : Synchronizable<SyncedConfig>.Default.EnemiesData[enemyType.enemyName]; public int SyncedScrapValue { get { return _syncedScrapValue.Value; } set { _syncedScrapValue.Value = value; } } public Dictionary<string, bool> AdditionalClientSettings { get; } = new Dictionary<string, bool>(); private void Awake() { EnemyAnimator = ((Component)this).gameObject.GetComponentInChildren<Animator>(); if ((Object)(object)EnemyAnimator == (Object)null) { Plugin.logger.LogWarning((object)("So somehow, the monster " + ((Object)((Component)this).gameObject).name + " does not have any Animator. Will work anyway but might have its animations glitched")); } ScanNode = ((Component)this).gameObject.GetComponentInChildren<ScanNodeProperties>(); if ((Object)(object)ScanNode == (Object)null) { Plugin.logger.LogWarning((object)("No ScanNode found in " + ((Object)((Component)this).gameObject).name + ". That's a weird enemy...")); } if (!base.itemProperties.saveItemVariable) { Plugin.logger.LogError((object)("Error: Enemy corpse saving was set to false for " + enemyType.enemyName)); } if (enemyType.enemyName == "Bunker Spider") { AdditionalClientSettings.TryAdd("ShowArachnophobeMesh", value: false); Plugin.logger.LogDebug((object)"Spider Safe tag added as false to Bunker Spider."); } } public override void Start() { ((GrabbableObject)this).Start(); if (((NetworkBehaviour)this).IsServer) { Plugin.logger.LogInfo((object)"Synchronizing the mob data and scrap values and positions with clients..."); EnemyData enemyData = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyType.enemyName]; if (GameNetworkManager.Instance.gameHasStarted || base.scrapValue == 0) { int syncedScrapValue = new Random().Next(enemyData.MinValue, enemyData.MaxValue); SyncedScrapValue = syncedScrapValue; } else { SyncedScrapValue = base.scrapValue; } } Plugin.logger.LogInfo((object)("Mob scrap " + enemyType.enemyName + " has spawned !")); if ((Object)(object)EnemyAnimator != (Object)null) { if (!EnemyData.Metadata.AnimateOnDeath) { ((Behaviour)EnemyAnimator).enabled = false; } try { EnemyAnimator.SetLayerWeight(2, 0f); } catch (Exception arg) { Plugin.logger.LogWarning((object)$"Failed to set layer 2's weight to 0 (bracken fix?). Error: {arg}"); ((Behaviour)EnemyAnimator).enabled = false; } try { EnemyAnimator.SetBool("Stunned", false); EnemyAnimator.SetBool("stunned", false); EnemyAnimator.SetBool("stun", false); EnemyAnimator.SetTrigger("KillEnemy"); EnemyAnimator.SetBool("Dead", true); ((MonoBehaviour)this).StartCoroutine(DisableAnimatorOnAnimationEnd()); } catch (Exception arg2) { Plugin.logger.LogError((object)$"Failed to set the enemy {((Object)((Component)this).gameObject).name} mob mesh animator to dead state. Maybe the animator doesn't have a dead state ? Error: {arg2}"); ((Behaviour)EnemyAnimator).enabled = false; } if (enemyType.enemyName == "Flowerman") { ((Component)EnemyAnimator).gameObject.SetActive(false); ((Component)EnemyAnimator).gameObject.SetActive(true); ((Behaviour)EnemyAnimator).enabled = false; } } if (Object.op_Implicit((Object)(object)ScanNode)) { EnemyData enemyData2 = (LocalConfig.Singleton.synchronizeRanks.Value ? Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyType.enemyName] : Synchronizable<SyncedConfig>.Default.EnemiesData[enemyType.enemyName]); ScanNodeProperties component = ((Component)ScanNode).GetComponent<ScanNodeProperties>(); component.scrapValue = SyncedScrapValue; component.subText = $"Rank:{enemyData2.Rank}\nValue: ${SyncedScrapValue}"; } else { Plugin.logger.LogError((object)("Enemy corpse " + base.itemProperties.itemName + " is missing a ScanNode !")); } if (enemyType.enemyName == "Bunker Spider") { ToggleArachnophobeMesh(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode); } } public void FixedUpdate() { if (enemyType.enemyName == "Bunker Spider") { if (!AdditionalClientSettings.TryGetValue("ShowArachnophobeMesh", out var value)) { AdditionalClientSettings.Add("ShowArachnophobeMesh", value: false); } if (value != IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode) { ToggleArachnophobeMesh(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode); } } } public override void PlayDropSFX() { ((GrabbableObject)this).PlayDropSFX(); if (enemyType.enemyName == "Bunker Spider") { ToggleArachnophobeMesh(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode); } } public override void GrabItem() { ((GrabbableObject)this).GrabItem(); if (enemyType.enemyName == "Bunker Spider") { ToggleArachnophobeMesh(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode); } } public void ToggleArachnophobeMesh(bool newStatus) { Plugin.logger.LogInfo((object)"Trying to update the Spider mesh to match arachnophobia settings..."); MeshRenderer component = ((Component)((Component)this).transform.GetChild(0).Find("MeshContainer").Find("AnimContainer") .Find("Armature") .Find("Abdomen") .Find("SpiderText")).GetComponent<MeshRenderer>(); SkinnedMeshRenderer component2 = ((Component)((Component)this).transform.GetChild(0).Find("MeshContainer").Find("MeshRenderer")).GetComponent<SkinnedMeshRenderer>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2)) { Plugin.logger.LogError((object)"This Spider mesh doesn't have a normal mesh or an arachnophobe mesh."); return; } AdditionalClientSettings["ShowArachnophobeMesh"] = newStatus; ((Renderer)component).enabled = newStatus; ((Renderer)component2).enabled = !newStatus; Plugin.logger.LogInfo((object)"The spider mesh have been updated to match player Arachnophobia settings !"); } public void SetScrapValue(int value) { Plugin.logger.LogInfo((object)$"Setting scrap value for {base.itemProperties.itemName}: {value}"); base.scrapValue = value; ScanNode.scrapValue = value; EnemyData enemyData = (LocalConfig.Singleton.synchronizeRanks.Value ? Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyType.enemyName] : Synchronizable<SyncedConfig>.Default.EnemiesData[enemyType.enemyName]); ScanNode.subText = $"Rank: {enemyData.Rank}\nValue: {value}"; } [IteratorStateMachine(typeof(<DisableAnimatorOnAnimationEnd>d__30))] public IEnumerator DisableAnimatorOnAnimationEnd() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DisableAnimatorOnAnimationEnd>d__30(0) { <>4__this = this }; } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); ((NetworkVariableBase)_syncedScrapValue).Initialize((NetworkBehaviour)(object)this); NetworkVariable<int> syncedScrapValue = _syncedScrapValue; syncedScrapValue.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Combine((Delegate?)(object)syncedScrapValue.OnValueChanged, (Delegate?)(object)(OnValueChangedDelegate<int>)delegate(int oldVal, int newVal) { SetScrapValue(newVal); }); } public override int GetItemDataToSave() { Plugin.logger.LogInfo((object)("GetItemData: Trying to save enemy scrap for " + base.itemProperties.itemName + ".")); return 0; } protected override void __initializeVariables() { if (_syncedScrapValue == null) { throw new Exception("EnemyScrap._syncedScrapValue cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)_syncedScrapValue).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)_syncedScrapValue, "_syncedScrapValue"); ((NetworkBehaviour)this).NetworkVariableFields.Add((NetworkVariableBase)(object)_syncedScrapValue); ((GrabbableObject)this).__initializeVariables(); } protected internal override string __getTypeName() { return "EnemyScrap"; } } } namespace EnhancedMonsters.Config { internal static class LethalConfigSupport { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static CanModifyDelegate <>9__3_1; public static GenericButtonHandler <>9__3_0; internal CanModifyResult <RegisterLethalConfig>b__3_1() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) return CanModifyResult.op_Implicit(!GameNetworkManager.Instance.gameHasStarted || !NetworkManager.Singleton.IsListening); } internal void <RegisterLethalConfig>b__3_0() { GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile; } } private static bool? lethalConfigLoaded; public static bool LethalConfigLoaded { get { bool valueOrDefault = lethalConfigLoaded.GetValueOrDefault(); if (!lethalConfigLoaded.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"); lethalConfigLoaded = valueOrDefault; } return lethalConfigLoaded.Value; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void RegisterLethalConfig(LocalConfig config) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_0104: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown LocalConfig config2 = config; LethalConfigManager.SetModDescription("Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements."); ConfigEntry<bool> synchronizeRanks = config2.synchronizeRanks; BoolCheckBoxOptions val = new BoolCheckBoxOptions { Name = "Synchronize Ranks", Section = "General", RequiresRestart = false }; object obj = <>c.<>9__3_1; if (obj == null) { CanModifyDelegate val2 = () => CanModifyResult.op_Implicit(!GameNetworkManager.Instance.gameHasStarted || !NetworkManager.Singleton.IsListening); <>c.<>9__3_1 = val2; obj = (object)val2; } ((BaseOptions)val).CanModifyCallback = (CanModifyDelegate)obj; BoolCheckBoxConfigItem val3 = new BoolCheckBoxConfigItem(synchronizeRanks, val); BoolCheckBoxConfigItem val4 = new BoolCheckBoxConfigItem(config2.dungeonSoundExchange, new BoolCheckBoxOptions { Name = "Dungeon Sound Exchange", Section = "Entrance Improvements", RequiresRestart = false }); ConfigEntry<int> dungeonSoundExchangeVolume = config2.dungeonSoundExchangeVolume; IntSliderOptions val5 = new IntSliderOptions { Name = "Dungeon Sound Exchange Volume", Section = "Entrance Improvements" }; ((BaseRangeOptions<int>)val5).Min = 0; ((BaseRangeOptions<int>)val5).Max = 100; ((BaseOptions)val5).RequiresRestart = false; ((BaseOptions)val5).CanModifyCallback = (CanModifyDelegate)(() => CanModifyResult.op_Implicit(config2.dungeonSoundExchange.Value)); IntSliderConfigItem val6 = new IntSliderConfigItem(dungeonSoundExchangeVolume, val5); object obj2 = <>c.<>9__3_0; if (obj2 == null) { GenericButtonHandler val7 = delegate { GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile; }; <>c.<>9__3_0 = val7; obj2 = (object)val7; } GenericButtonConfigItem val8 = new GenericButtonConfigItem("General", "Enemies Data", "All the enemies data are stored inside the file. You have a few rules to follow when editing the file or it will not work. Look at the github or thunderstore page for more info.", "Copy path", (GenericButtonHandler)obj2); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val3); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val8); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val4); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val6); } } internal static class LethalSettingsSupport { private static bool? lethalSettingsLoaded; public static bool LethalSettingsLoaded { get { bool valueOrDefault = lethalSettingsLoaded.GetValueOrDefault(); if (!lethalSettingsLoaded.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("com.willis.lc.lethalsettings"); lethalSettingsLoaded = valueOrDefault; } return lethalSettingsLoaded.Value; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void RegisterLethalSettings(LocalConfig config) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown LocalConfig config2 = config; Plugin.logger.LogInfo((object)"Registering lsSyncRank"); ToggleComponent val = new ToggleComponent { Enabled = true, Text = "Synchronize Ranks", Value = true, OnValueChanged = delegate(ToggleComponent comp, bool value) { config2.synchronizeRanks.Value = value; }, OnInitialize = delegate(ToggleComponent comp) { comp.Value = config2.synchronizeRanks.Value; comp.Enabled = !GameNetworkManager.Instance.gameHasStarted || !NetworkManager.Singleton.IsListening; } }; Plugin.logger.LogInfo((object)"Registering lsDungeonPrevQltComp"); Plugin.logger.LogInfo((object)"Registering lsDungeonPrevComponent"); Plugin.logger.LogInfo((object)"Registering lsDungeonSndVolComponent"); SliderComponent lsDungeonSndVolComponent = new SliderComponent { Enabled = false, Text = "[UNAVAILABLE] Dungeon Sound Exchange Volume", Value = 100f, MinValue = 0f, MaxValue = 100f, ShowValue = true, WholeNumbers = true, OnValueChanged = delegate(SliderComponent comp, float value) { config2.dungeonSoundExchangeVolume.Value = checked((int)value); }, OnInitialize = delegate(SliderComponent comp) { comp.Value = config2.dungeonSoundExchangeVolume.Value; } }; Plugin.logger.LogInfo((object)"Registering lsDungeonSndComponent"); ToggleComponent val2 = new ToggleComponent { Enabled = false, Text = "[UNAVAILABLE] Dungeon Sound Exchange", Value = true, OnValueChanged = delegate(ToggleComponent comp, bool value) { config2.dungeonSoundExchange.Value = value; lsDungeonSndVolComponent.Enabled = value; }, OnInitialize = delegate(ToggleComponent comp) { comp.Value = config2.dungeonSoundExchange.Value; lsDungeonSndVolComponent.Enabled = config2.dungeonSoundExchange.Value; } }; Plugin.logger.LogInfo((object)"Registering lsAccessEnemiesDataFile"); ButtonComponent val3 = new ButtonComponent { Enabled = true, ShowCaret = true, Text = "Copy path to Enemies Data file", OnClick = delegate { GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile; } }; Plugin.logger.LogInfo((object)"Registering mod info"); ModSettingsConfig val4 = new ModSettingsConfig(); val4.Id = "com.velddev.enhancedmonsters"; val4.Name = "Enhanced Monsters"; val4.Version = "1.3.13"; val4.Description = "Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements."; val4.MenuComponents = (MenuComponent[])(object)new MenuComponent[2] { (MenuComponent)val, (MenuComponent)val3 }; ModMenu.RegisterMod(val4); Plugin.logger.LogInfo((object)"Registered Mod Info"); } } public class LocalConfig { internal const string ModDesc = "Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements."; internal readonly bool SeamlessDungeonExists; public readonly ConfigEntry<bool> synchronizeRanks; public readonly ConfigEntry<bool> dungeonSoundExchange; public readonly ConfigEntry<int> dungeonSoundExchangeVolume; public static LocalConfig Singleton { get; private set; } public LocalConfig(ConfigFile cfg) { Singleton = this; SeamlessDungeonExists = Chainloader.PluginInfos.ContainsKey("tsundrella.seamlessdungeon"); synchronizeRanks = cfg.Bind<bool>("General", "Synchronize Ranks", true, "Wether or not to synchronize ranks of enemies from host's configs. It is recommended to keep it enabled. [NOTE: This setting can only be edited from the main menu.]"); dungeonSoundExchange = cfg.Bind<bool>("Entrance Improvements", "Unimplemented - Dungeon Sound Exchange", true, "Unimplemented - Wether to enable or not sound exchange between interior and exterior of the dungeon, next to entrance and fire exits. Disabling it can enhance performance on weakest configurations."); dungeonSoundExchangeVolume = cfg.Bind<int>("Entrance Improvements", "Unimplemented - Dungeon Sound Exchange Volume", 70, "Unimplemented - Volume level of sounds emitted from the interior/exterior when player is on the other side of the door."); if (LethalConfigSupport.LethalConfigLoaded) { Plugin.logger.LogInfo((object)"Loading LethalConfig settings"); LethalConfigSupport.RegisterLethalConfig(this); } if (LethalSettingsSupport.LethalSettingsLoaded) { Plugin.logger.LogInfo((object)"Loading LethalSettings settings"); LethalSettingsSupport.RegisterLethalSettings(this); } Plugin.logger.LogInfo((object)"Registering all settings."); } } [Serializable] public class SyncedConfig : Synchronizable<SyncedConfig> { public Dictionary<string, EnemyData> EnemiesData; [NonSerialized] public ConfigFile BepInConfigs; public SyncedConfig(ConfigFile cfg) { InitInstance(this); BepInConfigs = cfg; EnemiesData = EnemiesDataManager.EnemiesData; } public static void BroadcastSync() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!Synchronizable<SyncedConfig>.IsHost) { return; } Plugin.logger.LogDebug((object)"Host is broadcasting its config."); byte[] array = Synchronizable<SyncedConfig>.Serialize(Synchronizable<SyncedConfig>.Instance); int num = array.Length; int num2 = checked(FastBufferWriter.GetWriteSize<byte>(array, -1, 0) + Synchronizable<SyncedConfig>.IntSize); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num2, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); Synchronizable<SyncedConfig>.MessagingManager.SendNamedMessageToAll("EnhancedMonster_OnReceiveConfigSync", val, (NetworkDelivery)4); } catch (Exception arg) { Plugin.logger.LogError((object)$"The config sync broadcast lamentably failed lmao; here's the error: {arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void RequestSync() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!Synchronizable<SyncedConfig>.IsClient) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(Synchronizable<SyncedConfig>.IntSize, (Allocator)2, -1); try { Synchronizable<SyncedConfig>.MessagingManager.SendNamedMessage("EnhancedMonsters_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); Plugin.logger.LogInfo((object)"Asking host for their EnemyData config"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!Synchronizable<SyncedConfig>.IsHost) { return; } Plugin.logger.LogDebug((object)$"Config sync request received from client {clientId}"); byte[] array = Synchronizable<SyncedConfig>.Serialize(Synchronizable<SyncedConfig>.Instance); int num = array.Length; int writeSize = FastBufferWriter.GetWriteSize<byte>(array, -1, 0); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(checked(writeSize + Synchronizable<SyncedConfig>.IntSize), (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); Synchronizable<SyncedConfig>.MessagingManager.SendNamedMessage("EnhancedMonsters_OnReceiveConfigSync", clientId, val, (NetworkDelivery)4); } catch (Exception arg) { Plugin.logger.LogError((object)$"Coudln't sync configs between clients. Error: {arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(Synchronizable<SyncedConfig>.IntSize)) { Plugin.logger.LogError((object)"Config sync error: could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { Plugin.logger.LogError((object)$"Config sync error: Host could not sync. Error: The chunk of the buffer to read is larger than the remaining bytes chunk. {num} bytes to read, {checked(((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position)} remaining bytes"); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); Synchronizable<SyncedConfig>.SyncInstance(data); Plugin.logger.LogInfo((object)"Successfully synced config with host"); } } [Serializable] public class Synchronizable<T> { [NonSerialized] protected static int IntSize = 4; internal static CustomMessagingManager MessagingManager => NetworkManager.Singleton.CustomMessagingManager; internal static bool IsClient { get { NetworkManager singleton = NetworkManager.Singleton; return singleton != null && singleton.IsClient; } } internal static bool IsHost { get { NetworkManager singleton = NetworkManager.Singleton; return singleton != null && singleton.IsHost; } } public static T Default { get; set; } public static T Instance { get; set; } public static bool Synced { get; internal set; } protected void InitInstance(T instance) { Default = instance; Instance = instance; IntSize = 4; } internal static void SyncInstance(byte[] data) { Instance = Deserialize(data); Synced = true; } internal static void RevertSync() { Instance = Default; Synced = false; } public static byte[] Serialize(T val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { Plugin.logger.LogError((object)$"Error while serializing Config instance: {arg}"); return null; } } public static T Deserialize(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { Plugin.logger.LogError((object)$"Couldn't deserialize Config instance: {arg}"); return default(T); } } } } namespace EnhancedMonsters.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }