using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 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.9")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.9.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.9")]
[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");
public static ManualLogSource? logger;
internal static Plugin Singleton { 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.");
}
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.9";
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 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_03de: Unknown result type (might be due to invalid IL or missing references)
//IL_0450: Unknown result type (might be due to invalid IL or missing references)
//IL_056a: Unknown result type (might be due to invalid IL or missing references)
//IL_056f: Unknown result type (might be due to invalid IL or missing references)
//IL_0582: Unknown result type (might be due to invalid IL or missing references)
//IL_0587: Unknown result type (might be due to invalid IL or missing references)
//IL_059a: Unknown result type (might be due to invalid IL or missing references)
//IL_059f: 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, ((Object)val).name + " propized");
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;
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);
Enemies2Props.Add(enemyName, val5);
Plugin.logger.LogInfo((object)("Registered NetworkPrefab '" + ((Object)val5).name + "'/'" + ((Object)val2).name + "' (" + val6.itemName + ")"));
}
}
}
}
[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 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(new ReadOnlySpan<float>(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)
{
string text = ((!LocalConfig.Singleton.synchronizeRanks.Value) ? (Synchronizable<SyncedConfig>.Default.EnemiesData[__instance.enemyType.enemyName].Rank ?? "?") : (Synchronizable<SyncedConfig>.Instance.EnemiesData[__instance.enemyType.enemyName].Rank ?? "?"));
ScanNodeProperties componentInChildren = ((Component)__instance).gameObject.GetComponentInChildren<ScanNodeProperties>();
if (Object.op_Implicit((Object)(object)componentInChildren))
{
componentInChildren.subText = "Rank " + text;
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(EnemyAI), "KillEnemy")]
private static void KillEnemy(EnemyAI __instance, bool destroy)
{
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: 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 (!__instance.isEnemyDead)
{
__instance.isEnemyDead = true;
}
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("Start")]
public static void Start(GameNetworkManager __instance)
{
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();
}
[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.9</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();
}
}
}
namespace EnhancedMonsters.Monobehaviours
{
public class EnemyScrap : GrabbableObject
{
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);
}
}
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}";
}
public IEnumerator DisableAnimatorOnAnimationEnd()
{
AnimatorClipInfo[] currentClip = EnemyAnimator.GetCurrentAnimatorClipInfo(0);
if (currentClip.Length >= 1)
{
float deathAnimDuration = ((AnimatorClipInfo)(ref currentClip[0])).clip.length;
AnimatorStateInfo currentAnimatorStateInfo = EnemyAnimator.GetCurrentAnimatorStateInfo(0);
float deathAnimProgress = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime;
while (deathAnimProgress < deathAnimDuration)
{
yield return (object)new WaitForEndOfFrame();
}
((Behaviour)EnemyAnimator).enabled = false;
}
}
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.9";
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
{
}
}