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 Enhanced Monsters v1.4.0
BepInEx/plugins/EnhancedMonsters/EnhancedMonsters.dll
Decompiled 2 weeks 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.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.Networking; 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.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.4.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.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.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.4.0")] [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; } public static GameObject NetworkHandlerPrefab { get; private set; } private void Awake() { Singleton = this; logger = ((BaseUnityPlugin)this).Logger; new LocalConfig(((BaseUnityPlugin)this).Config); logger.LogInfo((object)"Local config initialized."); 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"); CreateNetworkHandlerPrefab(); logger.LogDebug((object)"EnhancedMonstersNetworkHandler network prefab registered"); 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)); harmony.PatchAll(typeof(MenuManager_Patches)); harmony.PatchAll(typeof(PlayerControllerB_Patches)); harmony.PatchAll(typeof(GameNetworkManager_Patches)); harmony.PatchAll(typeof(StartOfRound_Patches)); logger.LogDebug((object)"All Harmony 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>(); NetworkPrefabs.RegisterNetworkPrefab(val); EnemyToPropPrefab = val; } private static void CreateNetworkHandlerPrefab() { GameObject val = NetworkPrefabs.CreateNetworkPrefab("EnhancedMonstersNetworkHandler"); NetworkObject component = val.GetComponent<NetworkObject>(); component.AutoObjectParentSync = false; component.DontDestroyWithOwner = true; val.AddComponent<EnhancedMonstersNetworkHandler>(); NetworkPrefabs.RegisterNetworkPrefab(val); NetworkHandlerPrefab = val; } } public static class PluginInfo { public const int ConfigVersion = 11; public const string Version = "1.4.0"; 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 (SyncedConfig.Instance == null || SyncedConfig.IsHost || !NetworkManager.Singleton.IsListening) { SyncedConfig.BroadcastSync(); } } internal static void RegisterEnemy(string enemyName, EnemyData enemyData) { if (SyncedConfig.IsHost || !NetworkManager.Singleton.IsListening) { if (EnemiesData != 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 (!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 ScanAndRegisterUnknownEnemies() { EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>(); Plugin.logger.LogInfo((object)$"Scanning {array.Length} enemies for unknown entries"); 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 (!SyncedConfig.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName)) { 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 + "'")); } } SaveEnemiesData(); } public static void EnsureEnemy2PropPrefabs() { 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; } string enemyName = val.enemyType.enemyName; Plugin.logger.LogInfo((object)("Ensuring NetworkPrefab '" + enemyName + "'")); if (!TryUpdateExistingPrefab(val, enemyName) && SyncedConfig.Instance.EnemiesData.TryGetValue(enemyName, out var value) && value.Pickupable) { GameObject visual = BuildVisualCopy(val); GameObject val2 = BuildScrapPrefab(val, enemyName, visual, value); if (!((Object)(object)val2 == (Object)null)) { ScanNodeProperties componentInChildren = val2.GetComponentInChildren<ScanNodeProperties>(); Item enemyItem = BuildItemScriptable(enemyName, value, val2, componentInChildren); RegisterPrefabAndItem(enemyName, val2, enemyItem); } } } if (FarmingAndCookingSupport.FarmingAndCookingLoaded) { FarmingAndCookingSupport.RegisterFarmingAndCookingBodies(AllEnemiesScraps); } } private static bool TryUpdateExistingPrefab(EnemyAI enemy, string enemyName) { if (!Enemies2Props.TryGetValue(enemyName, out GameObject value)) { return false; } EnemyData enemyData = SyncedConfig.Instance.EnemiesData[enemyName]; if (!enemyData.Pickupable) { Enemies2Props.Remove(enemyName); return true; } EnemyScrap component = value.GetComponent<EnemyScrap>(); component.enemyType = enemy.enemyType; ((GrabbableObject)component).itemProperties.minValue = enemyData.MinValue; ((GrabbableObject)component).itemProperties.maxValue = enemyData.MaxValue; ((GrabbableObject)component).itemProperties.weight = enemyData.LCMass; return true; } private static GameObject BuildVisualCopy(EnemyAI enemy) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(((Object)enemy).name + " neutralized"); foreach (Transform item in ((Component)enemy).transform) { Transform val2 = item; if (!((Object)val2).name.StartsWith("MapDot") && !((Object)val2).name.StartsWith("Collider") && !((Object)val2).name.StartsWith("VoiceSFX") && !((Object)val2).name.StartsWith("CreatureSFX") && !((Object)val2).name.StartsWith("SeepingSFX") && !((Object)val2).name.StartsWith("CreatureVoice") && !((Object)val2).name.StartsWith("Ambience")) { Transform val3 = Object.Instantiate<Transform>(val2); ((Object)val3).name = ((Object)val2).name; ((Component)val3).transform.parent = val.transform; } } val.RemoveComponentsInChildren<Collider>(); val.RemoveComponentsInChildren<AudioLowPassFilter>(); val.RemoveComponentsInChildren<AudioReverbFilter>(); val.RemoveComponentsInChildren<OccludeAudio>(); val.RemoveComponentsInChildren<EnemyAICollisionDetect>(); val.RemoveComponentsInChildren<AudioSource>(); val.RemoveComponentsInChildren<ParticleSystem>(); val.RemoveComponentsInChildren<ParticleSystemRenderer>(); val.transform.localScale = ((Component)enemy).transform.localScale; return val; } private static GameObject BuildScrapPrefab(EnemyAI enemy, string enemyName, GameObject visual, EnemyData enemyData) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) GameObject val = NetworkPrefabs.CloneNetworkPrefab(Plugin.EnemyToPropPrefab, "Dead " + enemyName); visual.transform.parent = val.transform; Plugin.logger.LogInfo((object)("Attached " + ((Object)visual).name + " to " + ((Object)visual.transform.parent).name)); EnemyScrap component = val.GetComponent<EnemyScrap>(); component.EnemyGameObject = visual; CleanEnemyObj(component.EnemyGameObject); ((GrabbableObject)component).grabbable = true; ((GrabbableObject)component).grabbableToEnemies = false; component.enemyType = enemy.enemyType; BoxCollider component2 = val.GetComponent<BoxCollider>(); component2.size = enemyData.Metadata.CollisionExtents; if (enemyName == "Bunker Spider") { val.AddComponent<SpiderArachnophobiaToggle>(); } ScanNodeProperties componentInChildren = visual.GetComponentInChildren<ScanNodeProperties>(); if (!Object.op_Implicit((Object)(object)componentInChildren)) { Plugin.logger.LogWarning((object)("Enemy '" + enemyName + "' has no ScanNodeProperties; corpse cannot be networked-scanned. Discarding scrap prefab.")); Object.Destroy((Object)(object)val); return null; } Transform transform = ((Component)componentInChildren).gameObject.transform; ((Component)transform).transform.parent = val.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; return val; } private static Item BuildItemScriptable(string enemyName, EnemyData enemyData, GameObject scrapPrefab, ScanNodeProperties scanNodeProperties) { //IL_00c2: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) Item val = ScriptableObject.CreateInstance<Item>(); EnemyScrap component = scrapPrefab.GetComponent<EnemyScrap>(); ((GrabbableObject)component).itemProperties = val; ((Object)val).name = enemyName + " scrap"; val.itemName = scanNodeProperties.headerText; val.saveItemVariable = true; val.itemIcon = FastResourcesManager.EnemyScrapIcon; val.minValue = enemyData.MinValue; val.maxValue = enemyData.MaxValue; val.allowDroppingAheadOfPlayer = true; val.canBeGrabbedBeforeGameStart = true; val.isScrap = true; val.itemSpawnsOnGround = false; val.twoHanded = enemyData.Metadata.TwoHanded; val.requiresBattery = false; val.twoHandedAnimation = enemyData.Metadata.TwoHanded; val.weight = enemyData.LCMass; val.spawnPrefab = scrapPrefab; val.restingRotation = enemyData.Metadata.FloorRotation; val.rotationOffset = enemyData.Metadata.HandRotation; val.positionOffset = enemyData.Metadata.MeshOffset; EnemyData enemyData2 = SyncedConfig.Default.EnemiesData[enemyName]; val.dropSFX = ResolveSfx(enemyData2.Metadata.DropSFX); val.grabSFX = ResolveSfx(enemyData2.Metadata.GrabSFX); val.pocketSFX = ResolveSfx(enemyData2.Metadata.PocketSFX); return val; } private static AudioClip ResolveSfx(string sfxKey) { if (string.IsNullOrEmpty(sfxKey) || sfxKey == "none") { return null; } if (sfxKey == "default") { return FastResourcesManager.EnemyDropDefaultSound; } if (FastResourcesManager.CustomAudioClips.TryGetValue(sfxKey, out AudioClip value)) { return value; } Plugin.logger.LogWarning((object)("Custom SFX '" + sfxKey + "' not found in CustomAudioClips. Using default. (File missing or coroutine still running?)")); return FastResourcesManager.EnemyDropDefaultSound; } private static void RegisterPrefabAndItem(string enemyName, GameObject scrapPrefab, Item enemyItem) { NetworkPrefabs.RegisterNetworkPrefab(scrapPrefab); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && !singleton.NetworkConfig.Prefabs.Contains(scrapPrefab)) { singleton.AddNetworkPrefab(scrapPrefab); } Items.RegisterItem(enemyItem); Items.RegisterScrap(enemyItem, 0, (LevelTypes)1); AllEnemiesScraps.Add(enemyItem); Enemies2Props.Add(enemyName, scrapPrefab); Plugin.logger.LogInfo((object)("Registered NetworkPrefab '" + ((Object)scrapPrefab).name + "' (" + enemyItem.itemName + ")")); } 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 const string FarmingAndCookingGuid = "MelanieMelicious.FarmAndCook"; 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(Paths.ConfigPath, "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"); LoadCustomSounds(); } private static void LoadCustomSounds() { if (!Directory.Exists(CustomSoundsFolder)) { Directory.CreateDirectory(CustomSoundsFolder); Plugin.logger.LogInfo((object)("CustomSFX folder didn't exist, created at " + CustomSoundsFolder)); } string[] files = Directory.GetFiles(CustomSoundsFolder, "*.wav", SearchOption.TopDirectoryOnly); int num = 0; string[] array = files; foreach (string text in array) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); if (fileNameWithoutExtension == "default" || fileNameWithoutExtension == "none") { Plugin.logger.LogWarning((object)("Skipping '" + Path.GetFileName(text) + "': '" + fileNameWithoutExtension + "' is a reserved SFX key.")); continue; } if (CustomAudioClips.ContainsKey(fileNameWithoutExtension)) { Plugin.logger.LogWarning((object)("Skipping '" + Path.GetFileName(text) + "': key '" + fileNameWithoutExtension + "' already loaded.")); continue; } try { AudioClip value = LoadWav(text, fileNameWithoutExtension); CustomAudioClips[fileNameWithoutExtension] = value; num = checked(num + 1); Plugin.logger.LogInfo((object)("Loaded custom SFX '" + fileNameWithoutExtension + "' from " + Path.GetFileName(text))); } catch (Exception ex) { Plugin.logger.LogError((object)("Failed to load '" + Path.GetFileName(text) + "': " + ex.Message)); } } Plugin.logger.LogInfo((object)$"CustomSFX loading complete: {num} clip(s) loaded from {CustomSoundsFolder}"); } private static AudioClip LoadWav(string filePath, string key) { using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); using BinaryReader binaryReader = new BinaryReader(fileStream); if (FourCC(binaryReader) != "RIFF") { throw new InvalidDataException("Not a RIFF file"); } binaryReader.ReadInt32(); if (FourCC(binaryReader) != "WAVE") { throw new InvalidDataException("Not a WAVE file"); } short num = 0; short num2 = 0; int num3 = 0; short num4 = 0; byte[] array = null; checked { while (fileStream.Position < fileStream.Length) { string text = FourCC(binaryReader); int num5 = binaryReader.ReadInt32(); if (text == "fmt ") { num = binaryReader.ReadInt16(); num2 = binaryReader.ReadInt16(); num3 = binaryReader.ReadInt32(); binaryReader.ReadInt32(); binaryReader.ReadInt16(); num4 = binaryReader.ReadInt16(); int num6 = 16; if ((ushort)num == 65534 && num5 >= 40) { binaryReader.ReadInt16(); binaryReader.ReadInt16(); binaryReader.ReadInt32(); byte[] value = binaryReader.ReadBytes(16); num6 += 24; switch (BitConverter.ToInt32(value, 0)) { case 1: num = 1; break; case 3: num = 3; break; } } if (num5 > num6) { fileStream.Seek(num5 - num6, SeekOrigin.Current); } } else { if (text == "data") { array = binaryReader.ReadBytes(num5); break; } fileStream.Seek(num5, SeekOrigin.Current); } } if (array == null) { throw new InvalidDataException("No 'data' chunk found"); } } float[] array2; if (num == 1 && num4 == 16) { int num7 = array.Length / 2; array2 = new float[num7]; checked { for (int i = 0; i < num7; i++) { short num8 = (short)(array[i * 2] | (array[i * 2 + 1] << 8)); array2[i] = (float)num8 / 32768f; } } } else if (num == 1 && num4 == 24) { int num9 = array.Length / 3; array2 = new float[num9]; for (int j = 0; j < num9; j = checked(j + 1)) { int num10 = checked(array[j * 3] | (array[j * 3 + 1] << 8) | (array[j * 3 + 2] << 16)); if (((uint)num10 & 0x800000u) != 0) { num10 |= -16777216; } array2[j] = (float)num10 / 8388608f; } } else if (num == 1 && num4 == 32) { int num11 = array.Length / 4; array2 = new float[num11]; checked { for (int k = 0; k < num11; k++) { int num12 = array[k * 4] | (array[k * 4 + 1] << 8) | (array[k * 4 + 2] << 16) | (array[k * 4 + 3] << 24); array2[k] = (float)num12 / 2.1474836E+09f; } } } else { if (num != 3 || num4 != 32) { throw new InvalidDataException($"Unsupported WAV format (format={num}, bits={num4}). Use 16/24/32-bit PCM or 32-bit IEEE float."); } int num13 = array.Length / 4; array2 = new float[num13]; Buffer.BlockCopy(array, 0, array2, 0, array.Length); } int num14 = array2.Length / num2; AudioClip val = AudioClip.Create("EM_CSFX_" + key, num14, (int)num2, num3, false); val.SetData(array2, 0); return val; } private static string FourCC(BinaryReader reader) { return Encoding.ASCII.GetString(reader.ReadBytes(4)); } } internal static class KnownEnemies { public const string BunkerSpider = "Bunker Spider"; public const string Flowerman = "Flowerman"; public const string SandSpider = "SandSpider"; public const string Maneater = "Maneater"; } 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); } } } } 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 ? SyncedConfig.Instance : 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)) { ScanNodeProperties componentInChildren = ((Component)__instance).gameObject.GetComponentInChildren<ScanNodeProperties>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.subText = "Rank " + value.Rank; } } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "KillEnemy")] private static void KillEnemy(EnemyAI __instance, bool destroy) { //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: 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 (!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) { return; } 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); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(-10000f, -10000f, -10000f); ((Component)__instance).transform.position = val2; __instance.serverPosition = val2; NetworkObject component = ((Component)__instance).GetComponent<NetworkObject>(); EnhancedMonstersNetworkHandler instance = EnhancedMonstersNetworkHandler.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)component != (Object)null) { instance.HideOriginalEnemyBodyClientRpc(NetworkObjectReference.op_Implicit(component), val2); } else { Plugin.logger.LogWarning((object)"Network handler or enemy NetworkObject unavailable; falling back to SyncPositionToClients()"); __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() { SyncedConfig.RevertSync(); } } [HarmonyPatch(typeof(MenuManager))] public class MenuManager_Patches { [HarmonyPostfix] [HarmonyPatch(typeof(MenuManager), "Start")] private static void Start(MenuManager __instance) { //IL_0077: 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.4.0</size>"; ((Component)__instance.versionNumberText).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(500f, 50f); EnemiesDataManager.ScanAndRegisterUnknownEnemies(); EnemiesDataManager.EnsureEnemy2PropPrefabs(); Plugin.logger.LogInfo((object)"All enemies have been patched correctly."); } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerB_Patches { [HarmonyPrefix] [HarmonyPatch("ConnectClientToPlayerObject")] public static void InitializeLocalPlayerPrefabs() { EnemiesDataManager.ScanAndRegisterUnknownEnemies(); EnemiesDataManager.EnsureEnemy2PropPrefabs(); } [HarmonyPostfix] [HarmonyPatch("ConnectClientToPlayerObject")] public static void InitializeLocalPlayer() { if (SyncedConfig.IsHost) { Plugin.logger.LogInfo((object)"Local player is host, no sync request needed"); } else { SyncedConfig.RequestSync(); } } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRound_Patches { [HarmonyPostfix] [HarmonyPatch("Start")] public static void StartPatch() { EnemiesDataManager.ScanAndRegisterUnknownEnemies(); EnemiesDataManager.EnsureEnemy2PropPrefabs(); if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && (Object)(object)Plugin.NetworkHandlerPrefab != (Object)null) { GameObject val = Object.Instantiate<GameObject>(Plugin.NetworkHandlerPrefab); val.GetComponent<NetworkObject>().Spawn(true); Plugin.logger.LogInfo((object)"EnhancedMonstersNetworkHandler spawned by server in StartOfRound"); } } } } namespace EnhancedMonsters.Networking { public class EnhancedMonstersNetworkHandler : NetworkBehaviour { public static EnhancedMonstersNetworkHandler Instance { get; private set; } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); Instance = this; if (((NetworkBehaviour)this).IsServer) { ConfigSyncService.Synced = true; } Plugin.logger.LogInfo((object)("EnhancedMonstersNetworkHandler spawned (" + (((NetworkBehaviour)this).IsServer ? "server" : "client") + ")")); } public override void OnNetworkDespawn() { ((NetworkBehaviour)this).OnNetworkDespawn(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } Plugin.logger.LogInfo((object)"EnhancedMonstersNetworkHandler despawned"); } [ServerRpc(RequireOwnership = false)] public void RequestConfigSyncServerRpc(ServerRpcParams serverRpcParams = default(ServerRpcParams)) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_0126: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0150: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(3276370873u, serverRpcParams, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendServerRpc(ref val, 3276370873u, serverRpcParams, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost)) { return; } base.__rpc_exec_stage = (__RpcExecStage)0; if (((NetworkBehaviour)this).IsServer) { ulong senderClientId = serverRpcParams.Receive.SenderClientId; Plugin.logger.LogDebug((object)$"ConfigSync request received from client {senderClientId}"); byte[] array = ConfigSyncService.SerializeCurrent(); if (array.Length == 0) { Plugin.logger.LogError((object)"Aborting sync response: empty payload"); return; } ClientRpcParams val2 = default(ClientRpcParams); val2.Send = new ClientRpcSendParams { TargetClientIds = new ulong[1] { senderClientId } }; ClientRpcParams clientRpcParams = val2; ReceiveConfigSyncClientRpc(array, clientRpcParams); } } [ClientRpc] public void ReceiveConfigSyncClientRpc(byte[] data, ClientRpcParams clientRpcParams = default(ClientRpcParams)) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(2833577898u, clientRpcParams, (RpcDelivery)0); bool flag = data != null; ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val)).WriteValueSafe<byte>(data, default(ForPrimitives)); } ((NetworkBehaviour)this).__endSendClientRpc(ref val, 2833577898u, clientRpcParams, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost)) { base.__rpc_exec_stage = (__RpcExecStage)0; if (!((NetworkBehaviour)this).IsServer) { Plugin.logger.LogInfo((object)$"Received config sync via ClientRpc, {((data != null) ? data.Length : 0)} bytes"); ConfigSyncService.ApplyReceivedSync(data); } } } [ClientRpc] public void BroadcastConfigSyncClientRpc(byte[] data) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(149726897u, val, (RpcDelivery)0); bool flag = data != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(data, default(ForPrimitives)); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 149726897u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost)) { base.__rpc_exec_stage = (__RpcExecStage)0; if (!((NetworkBehaviour)this).IsServer) { Plugin.logger.LogInfo((object)$"Received config broadcast via ClientRpc, {((data != null) ? data.Length : 0)} bytes"); ConfigSyncService.ApplyReceivedSync(data); } } } [ClientRpc] public void HideOriginalEnemyBodyClientRpc(NetworkObjectReference originalEnemyRef, Vector3 hidePosition) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1086037223u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref originalEnemyRef, default(ForNetworkSerializable)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref hidePosition); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1086037223u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } base.__rpc_exec_stage = (__RpcExecStage)0; if (((NetworkBehaviour)this).IsServer) { return; } NetworkObject val3 = default(NetworkObject); if (!((NetworkObjectReference)(ref originalEnemyRef)).TryGet(ref val3, (NetworkManager)null)) { Plugin.logger.LogWarning((object)"HideOriginalEnemyBodyClientRpc: could not resolve enemy NetworkObject; skipping client-side teleport"); return; } ((Component)val3).transform.position = hidePosition; EnemyAI component = ((Component)val3).GetComponent<EnemyAI>(); if ((Object)(object)component != (Object)null) { component.serverPosition = hidePosition; } Plugin.logger.LogDebug((object)$"Hid original enemy body '{((Object)((Component)val3).gameObject).name}' at {hidePosition}"); } protected override void __initializeVariables() { ((NetworkBehaviour)this).__initializeVariables(); } protected override void __initializeRpcs() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown ((NetworkBehaviour)this).__registerRpc(3276370873u, new RpcReceiveHandler(__rpc_handler_3276370873), "RequestConfigSyncServerRpc"); ((NetworkBehaviour)this).__registerRpc(2833577898u, new RpcReceiveHandler(__rpc_handler_2833577898), "ReceiveConfigSyncClientRpc"); ((NetworkBehaviour)this).__registerRpc(149726897u, new RpcReceiveHandler(__rpc_handler_149726897), "BroadcastConfigSyncClientRpc"); ((NetworkBehaviour)this).__registerRpc(1086037223u, new RpcReceiveHandler(__rpc_handler_1086037223), "HideOriginalEnemyBodyClientRpc"); ((NetworkBehaviour)this).__initializeRpcs(); } private static void __rpc_handler_3276370873(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { ServerRpcParams server = rpcParams.Server; target.__rpc_exec_stage = (__RpcExecStage)1; ((EnhancedMonstersNetworkHandler)(object)target).RequestConfigSyncServerRpc(server); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_2833577898(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); byte[] data = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref data, default(ForPrimitives)); } ClientRpcParams client = rpcParams.Client; target.__rpc_exec_stage = (__RpcExecStage)1; ((EnhancedMonstersNetworkHandler)(object)target).ReceiveConfigSyncClientRpc(data, client); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_149726897(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); byte[] data = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref data, default(ForPrimitives)); } target.__rpc_exec_stage = (__RpcExecStage)1; ((EnhancedMonstersNetworkHandler)(object)target).BroadcastConfigSyncClientRpc(data); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_1086037223(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { NetworkObjectReference originalEnemyRef = default(NetworkObjectReference); ((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref originalEnemyRef, default(ForNetworkSerializable)); Vector3 hidePosition = default(Vector3); ((FastBufferReader)(ref reader)).ReadValueSafe(ref hidePosition); target.__rpc_exec_stage = (__RpcExecStage)1; ((EnhancedMonstersNetworkHandler)(object)target).HideOriginalEnemyBodyClientRpc(originalEnemyRef, hidePosition); target.__rpc_exec_stage = (__RpcExecStage)0; } } protected internal override string __getTypeName() { return "EnhancedMonstersNetworkHandler"; } } } namespace EnhancedMonsters.Monobehaviours { public class EnemyScrap : GrabbableObject { [CompilerGenerated] private sealed class <DisableAnimatorOnAnimationEnd>d__22 : 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__22(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); public Animator EnemyAnimator { get; private set; } public ScanNodeProperties ScanNode { get; private set; } public GameObject EnemyGameObject { get; set; } public EnemyData EnemyData => LocalConfig.Singleton.synchronizeRanks.Value ? SyncedConfig.Instance.EnemiesData[enemyType.enemyName] : SyncedConfig.Default.EnemiesData[enemyType.enemyName]; public int SyncedScrapValue { get { return _syncedScrapValue.Value; } set { _syncedScrapValue.Value = value; } } 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)); } } 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 = 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 ? SyncedConfig.Instance.EnemiesData[enemyType.enemyName] : 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 !")); } } 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 ? SyncedConfig.Instance.EnemiesData[enemyType.enemyName] : SyncedConfig.Default.EnemiesData[enemyType.enemyName]); ScanNode.subText = $"Rank: {enemyData.Rank}\nValue: {value}"; } [IteratorStateMachine(typeof(<DisableAnimatorOnAnimationEnd>d__22))] public IEnumerator DisableAnimatorOnAnimationEnd() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DisableAnimatorOnAnimationEnd>d__22(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 override void __initializeRpcs() { ((GrabbableObject)this).__initializeRpcs(); } protected internal override string __getTypeName() { return "EnemyScrap"; } } public class SpiderArachnophobiaToggle : MonoBehaviour { private MeshRenderer _safeMesh; private SkinnedMeshRenderer _normalMesh; private bool _renderersResolved; private void Start() { ResolveRenderers(); ApplyArachnophobeMode(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode); } private void LateUpdate() { ApplyArachnophobeMode(IngamePlayerSettings.Instance.unsavedSettings.spiderSafeMode); } public void ApplyArachnophobeMode(bool arachnophobeEnabled) { if (!_renderersResolved) { ResolveRenderers(); } if (!((Object)(object)_safeMesh == (Object)null) && !((Object)(object)_normalMesh == (Object)null)) { if (((Renderer)_safeMesh).enabled != arachnophobeEnabled) { ((Renderer)_safeMesh).enabled = arachnophobeEnabled; } if (((Renderer)_normalMesh).enabled != !arachnophobeEnabled) { ((Renderer)_normalMesh).enabled = !arachnophobeEnabled; } } } private void ResolveRenderers() { if (((Component)this).transform.childCount == 0) { return; } Transform child = ((Component)this).transform.GetChild(0); Transform obj = child.Find("MeshContainer"); object obj2; if (obj == null) { obj2 = null; } else { Transform obj3 = obj.Find("AnimContainer"); if (obj3 == null) { obj2 = null; } else { Transform obj4 = obj3.Find("Armature"); if (obj4 == null) { obj2 = null; } else { Transform obj5 = obj4.Find("Abdomen"); obj2 = ((obj5 != null) ? obj5.Find("SpiderText") : null); } } } Transform val = (Transform)obj2; Transform obj6 = child.Find("MeshContainer"); Transform val2 = ((obj6 != null) ? obj6.Find("MeshRenderer") : null); _safeMesh = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<MeshRenderer>() : null); _normalMesh = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<SkinnedMeshRenderer>() : null); if ((Object)(object)_safeMesh == (Object)null || (Object)(object)_normalMesh == (Object)null) { Plugin.logger.LogError((object)"This Spider mesh doesn't have a normal mesh or an arachnophobe mesh."); } else { _renderersResolved = true; } } } } namespace EnhancedMonsters.Config { internal static class ConfigSyncService { [CompilerGenerated] private sealed class <WaitForHandlerAndRequest>d__19 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private float <waited>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForHandlerAndRequest>d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <waited>5__1 = 0f; break; case 1: <>1__state = -1; <waited>5__1 += 0.25f; break; } if ((Object)(object)EnhancedMonstersNetworkHandler.Instance == (Object)null && <waited>5__1 < 10f) { <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 1; return true; } if ((Object)(object)EnhancedMonstersNetworkHandler.Instance != (Object)null) { EnhancedMonstersNetworkHandler.Instance.RequestConfigSyncServerRpc(); Plugin.logger.LogInfo((object)$"Config sync request sent after {<waited>5__1:0.00}s wait"); } else { Plugin.logger.LogWarning((object)$"Config sync handler did not appear within {10f}s, giving up"); } 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 static SyncedConfig Default { get; private set; } public static SyncedConfig Instance { get; private set; } public static bool Synced { get; internal set; } public static bool IsHost { get { NetworkManager singleton = NetworkManager.Singleton; return singleton != null && singleton.IsHost; } } public static bool IsClient { get { NetworkManager singleton = NetworkManager.Singleton; return singleton != null && singleton.IsClient; } } public static void Initialize(SyncedConfig defaults) { Default = defaults; Instance = defaults; Synced = false; } public static void RevertSync() { Instance = Default; Synced = false; Plugin.logger.LogInfo((object)"Reverting sync, Instance=Default, Synced=false"); } public static void RequestSync() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!IsClient || IsHost) { return; } if ((Object)(object)EnhancedMonstersNetworkHandler.Instance != (Object)null) { EnhancedMonstersNetworkHandler.Instance.RequestConfigSyncServerRpc(); Plugin.logger.LogInfo((object)"Requesting config sync via ServerRpc"); return; } Plugin.logger.LogInfo((object)"EnhancedMonstersNetworkHandler not yet spawned, scheduling retry"); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { ((MonoBehaviour)instance).StartCoroutine(WaitForHandlerAndRequest()); } else { Plugin.logger.LogWarning((object)"StartOfRound.Instance is null, cannot schedule sync retry"); } } [IteratorStateMachine(typeof(<WaitForHandlerAndRequest>d__19))] private static IEnumerator WaitForHandlerAndRequest() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForHandlerAndRequest>d__19(0); } public static void BroadcastSync() { if (!IsHost) { return; } EnhancedMonstersNetworkHandler instance = EnhancedMonstersNetworkHandler.Instance; if ((Object)(object)instance == (Object)null) { Plugin.logger.LogDebug((object)"BroadcastSync: handler not spawned yet, skipping"); return; } byte[] array = SerializeCurrent(); if (array.Length != 0) { instance.BroadcastConfigSyncClientRpc(array); Plugin.logger.LogInfo((object)$"Host broadcast config sync, {array.Length} bytes"); } } public static byte[] SerializeCurrent() { if (Instance == null) { Plugin.logger.LogError((object)"SerializeCurrent: Instance is null"); return Array.Empty<byte>(); } try { string s = JsonConvert.SerializeObject((object)Instance.EnemiesData); return Encoding.UTF8.GetBytes(s); } catch (Exception arg) { Plugin.logger.LogError((object)$"Failed to serialize sync payload: {arg}"); return Array.Empty<byte>(); } } public static void ApplyReceivedSync(byte[] data) { if (data == null || data.Length == 0) { Plugin.logger.LogError((object)"ApplyReceivedSync: empty payload"); return; } if (Instance == null) { Plugin.logger.LogError((object)"ApplyReceivedSync: Instance is null, cannot apply"); return; } try { string @string = Encoding.UTF8.GetString(data); Dictionary<string, EnemyData> dictionary = JsonConvert.DeserializeObject<Dictionary<string, EnemyData>>(@string); if (dictionary == null) { Plugin.logger.LogError((object)"ApplyReceivedSync: deserialization returned null"); return; } EnemiesDataManager.EnemiesData.Clear(); foreach (KeyValuePair<string, EnemyData> item in dictionary) { EnemiesDataManager.EnemiesData[item.Key] = item.Value; } Synced = true; Plugin.logger.LogInfo((object)$"Applied sync, {dictionary.Count} entries, Synced=true"); } catch (Exception arg) { Plugin.logger.LogError((object)$"Failed to apply sync payload: {arg}"); } } } 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_002f: 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_0062: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown LethalConfigManager.SetModDescription("Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements."); ConfigEntry<bool> synchronizeRanks = config.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); object obj2 = <>c.<>9__3_0; if (obj2 == null) { GenericButtonHandler val4 = delegate { GUIUtility.systemCopyBuffer = EnemiesDataManager.EnemiesDataFile; }; <>c.<>9__3_0 = val4; obj2 = (object)val4; } GenericButtonConfigItem val5 = 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)val5); } } 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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 lsAccessEnemiesDataFile"); ButtonComponent val2 = 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 val3 = new ModSettingsConfig(); val3.Id = "com.velddev.enhancedmonsters"; val3.Name = "Enhanced Monsters"; val3.Version = "1.4.0"; val3.Description = "Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements."; val3.MenuComponents = (MenuComponent[])(object)new MenuComponent[2] { (MenuComponent)val, (MenuComponent)val2 }; ModMenu.RegisterMod(val3); 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."; public readonly ConfigEntry<bool> synchronizeRanks; public static LocalConfig Singleton { get; private set; } public LocalConfig(ConfigFile cfg) { Singleton = this; 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.]"); 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."); } } public class SyncedConfig { public Dictionary<string, EnemyData> EnemiesData; public ConfigFile BepInConfigs; public static SyncedConfig Default => ConfigSyncService.Default; public static SyncedConfig Instance => ConfigSyncService.Instance; public static bool Synced => ConfigSyncService.Synced; public static bool IsHost => ConfigSyncService.IsHost; public static bool IsClient => ConfigSyncService.IsClient; public SyncedConfig(ConfigFile cfg) { BepInConfigs = cfg; EnemiesData = EnemiesDataManager.EnemiesData; ConfigSyncService.Initialize(this); } public static void BroadcastSync() { ConfigSyncService.BroadcastSync(); } public static void RequestSync() { ConfigSyncService.RequestSync(); } public static void RevertSync() { ConfigSyncService.RevertSync(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { } } } namespace EnhancedMonsters.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }