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 ToilHead v1.9.1
com.github.zehsteam.ToilHead.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalLib.Modules; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using com.github.zehsteam.ToilHead.Compatibility; using com.github.zehsteam.ToilHead.MonoBehaviours; using com.github.zehsteam.ToilHead.MonoBehaviours.TurretHeads; using com.github.zehsteam.ToilHead.NetcodePatcher; using com.github.zehsteam.ToilHead.Patches; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Zehs")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 Zehs")] [assembly: AssemblyDescription("[v81+] CoilHeads, Manticoils, and other entities can sometimes spawn with a turret on their head. Highly Configurable.")] [assembly: AssemblyFileVersion("1.9.1.0")] [assembly: AssemblyInformationalVersion("1.9.1+6ad373a695477ab74224e1012f441abf586aae0c")] [assembly: AssemblyProduct("ToilHead")] [assembly: AssemblyTitle("com.github.zehsteam.ToilHead")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.9.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace com.github.zehsteam.ToilHead { public static class Api { public static Dictionary<EnemyAI, TurretHeadControllerBehaviour> EnemyTurretHeadControllerPairs => TurretHeadManager.EnemyTurretHeadControllerPairs; public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> PlayerTurretHeadControllerPairs => TurretHeadManager.PlayerTurretHeadControllerPairs; public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> DeadBodyTurretHeadControllerPairs => TurretHeadManager.DeadBodyTurretHeadControllerPairs; public static TurretHeadData ToilHeadData => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false); public static bool ForceToilHeadSpawns { get { return ToilHeadData.ForceSpawns; } set { ToilHeadData.ForceSpawns = value; } } public static int ForceToilHeadMaxSpawnCount { get { return ToilHeadData.ForceMaxSpawnCount; } set { ToilHeadData.ForceMaxSpawnCount = value; } } public static TurretHeadData MantiToilData => TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false); public static bool ForceMantiToilSpawns { get { return MantiToilData.ForceSpawns; } set { MantiToilData.ForceSpawns = value; } } public static int ForceMantiToilMaxSpawnCount { get { return MantiToilData.ForceMaxSpawnCount; } set { MantiToilData.ForceMaxSpawnCount = value; } } public static TurretHeadData ToilSlayerData => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true); public static bool ForceToilSlayerSpawns { get { return ToilSlayerData.ForceSpawns; } set { ToilSlayerData.ForceSpawns = value; } } public static int ForceToilSlayerMaxSpawnCount { get { return ToilSlayerData.ForceMaxSpawnCount; } set { ToilSlayerData.ForceMaxSpawnCount = value; } } public static TurretHeadData MantiSlayerData => TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: true); public static bool ForceMantiSlayerSpawns { get { return MantiSlayerData.ForceSpawns; } set { MantiSlayerData.ForceSpawns = value; } } public static int ForceMantiSlayerMaxSpawnCount { get { return MantiSlayerData.ForceMaxSpawnCount; } set { MantiSlayerData.ForceMaxSpawnCount = value; } } public static TurretHeadData ToilPlayerData => TurretHeadManager.PlayerTurretHeadData; public static bool ForceToilPlayerSpawns { get { return ToilPlayerData.ForceSpawns; } set { ToilPlayerData.ForceSpawns = value; } } public static int ForceToilPlayerMaxSpawnCount { get { return ToilPlayerData.ForceMaxSpawnCount; } set { ToilPlayerData.ForceMaxSpawnCount = value; } } public static TurretHeadData ToilMaskedData => TurretHeadManager.GetEnemyTurretHeadData("Masked", isSlayer: false); public static bool ForceToilMaskedSpawns { get { return ToilMaskedData.ForceSpawns; } set { ToilMaskedData.ForceSpawns = value; } } public static int ForceToilMaskedMaxSpawnCount { get { return ToilMaskedData.ForceMaxSpawnCount; } set { ToilMaskedData.ForceMaxSpawnCount = value; } } public static TurretHeadData SlayerMaskedData => TurretHeadManager.GetEnemyTurretHeadData("Masked", isSlayer: true); public static bool ForceSlayerMaskedSpawns { get { return SlayerMaskedData.ForceSpawns; } set { SlayerMaskedData.ForceSpawns = value; } } public static int ForceSlayerMaskedMaxSpawnCount { get { return SlayerMaskedData.ForceMaxSpawnCount; } set { SlayerMaskedData.ForceMaxSpawnCount = value; } } [Obsolete("EnemyTurretPairs is deprecated, please use EnemyTurretHeadControllerPairs instead.", true)] public static Dictionary<EnemyAI, ToilHeadTurretBehaviour> EnemyTurretPairs => new Dictionary<EnemyAI, ToilHeadTurretBehaviour>(); [Obsolete("PlayerTurretPairs is deprecated, please use PlayerTurretHeadControllerPairs instead.", true)] public static Dictionary<PlayerControllerB, ToilHeadTurretBehaviour> PlayerTurretPairs => new Dictionary<PlayerControllerB, ToilHeadTurretBehaviour>(); [Obsolete("enemyTurretPairs is deprecated, please use EnemyTurretHeadControllerPairs instead.", true)] public static Dictionary<NetworkObject, NetworkObject> enemyTurretPairs => new Dictionary<NetworkObject, NetworkObject>(); [Obsolete("MaxSpawnCount is deprecated, please use ToilHeadMaxSpawnCount instead.", true)] public static int MaxSpawnCount => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).GetSpawnDataForCurrentMoon().MaxSpawnCount; [Obsolete("SpawnChance is deprecated, please use ToilHeadSpawnChance instead.", true)] public static float SpawnChance => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).GetSpawnDataForCurrentMoon().SpawnChance; [Obsolete("spawnCount is deprecated, please use ToilHeadSpawnCount instead.", true)] public static int spawnCount => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).SpawnCount; [Obsolete("forceSpawns is deprecated, please use ForceToilHeadSpawns instead.", true)] public static bool forceSpawns { get { return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceSpawns; } set { TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceSpawns = value; } } [Obsolete("forceMaxSpawnCount is deprecated, please use ForceToilHeadMaxSpawnCount instead.", true)] public static int forceMaxSpawnCount { get { return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceMaxSpawnCount; } set { TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: false).ForceMaxSpawnCount = value; } } [Obsolete("mantiToilSpawnCount is deprecated, please use MantiToilSpawnCount instead.", true)] public static int mantiToilSpawnCount => TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).SpawnCount; [Obsolete("forceMantiToilSpawns is deprecated, please use ForceMantiToilSpawns instead.", true)] public static bool forceMantiToilSpawns { get { return TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceSpawns; } set { TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceSpawns = value; } } [Obsolete("forceMantiToilMaxSpawnCount is deprecated, please use ForceMantiToilMaxSpawnCount instead.", true)] public static int forceMantiToilMaxSpawnCount { get { return TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceMaxSpawnCount; } set { TurretHeadManager.GetEnemyTurretHeadData("Manticoil", isSlayer: false).ForceMaxSpawnCount = value; } } [Obsolete("toilSlayerSpawnCount is deprecated, please use ToilSlayerSpawnCount instead.", true)] public static int toilSlayerSpawnCount => TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).SpawnCount; [Obsolete("forceToilSlayerSpawns is deprecated, please use ForceToilSlayerSpawns instead.", true)] public static bool forceToilSlayerSpawns { get { return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceSpawns; } set { TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceSpawns = value; } } [Obsolete("forceToilSlayerMaxSpawnCount is deprecated, please use ForceToilSlayerMaxSpawnCount instead.", true)] public static int forceToilSlayerMaxSpawnCount { get { return TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceMaxSpawnCount; } set { TurretHeadManager.GetEnemyTurretHeadData("Spring", isSlayer: true).ForceMaxSpawnCount = value; } } public static bool SetToilHeadOnServer(EnemyAI enemyScript) { return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: false); } public static bool SetMantiToilOnServer(EnemyAI enemyScript) { return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: false); } public static bool SetToilSlayerOnServer(EnemyAI enemyScript) { return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: true); } public static bool SetMantiSlayerOnServer(EnemyAI enemyScript) { return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: true); } public static bool SetToilPlayerOnServer(PlayerControllerB playerScript, bool isSlayer = false) { return TurretHeadManager.SetPlayerTurretHeadOnServer(playerScript, isSlayer); } public static bool SetToilMaskedOnServer(EnemyAI enemyScript) { return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: false); } public static bool SetSlayerMaskedOnServer(EnemyAI enemyScript) { return TurretHeadManager.SetEnemyTurretHeadOnServer(enemyScript, isSlayer: true); } } internal static class Content { public static GameObject NetworkHandlerPrefab; public static GameObject TurretPropPrefab; public static GameObject MinigunPropPrefab; public static GameObject ToilPlayerControllerPrefab; public static GameObject SlayerPlayerControllerPrefab; public static GameObject ToiledDeadBodyControllerPrefab; public static GameObject SlayedDeadBodyControllerPrefab; public static GameObject ToilHeadControllerPrefab; public static GameObject ToilSlayerControllerPrefab; public static GameObject MantiToilControllerPrefab; public static GameObject MantiSlayerControllerPrefab; public static GameObject ToilMaskedControllerPrefab; public static GameObject SlayerMaskedControllerPrefab; public static Item ToilHeadPlush; public static Item ToilSlayerPlush; public static void Load() { LoadAssetsFromAssetBundle(); } private static void LoadAssetsFromAssetBundle() { try { string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location); string text = Path.Combine(directoryName, "toilhead_assets"); AssetBundle val = AssetBundle.LoadFromFile(text); NetworkHandlerPrefab = val.LoadAsset<GameObject>("NetworkHandler"); NetworkHandlerPrefab.AddComponent<PluginNetworkBehaviour>(); TurretPropPrefab = val.LoadAsset<GameObject>("TurretHeadTurretProp"); MinigunPropPrefab = val.LoadAsset<GameObject>("MinigunTurretHeadTurretProp"); ToilPlayerControllerPrefab = val.LoadAsset<GameObject>("ToilPlayerController"); SlayerPlayerControllerPrefab = val.LoadAsset<GameObject>("SlayerPlayerController"); ToiledDeadBodyControllerPrefab = val.LoadAsset<GameObject>("ToiledDeadBodyController"); SlayedDeadBodyControllerPrefab = val.LoadAsset<GameObject>("SlayedDeadBodyController"); ToilHeadControllerPrefab = val.LoadAsset<GameObject>("ToilHeadController"); ToilSlayerControllerPrefab = val.LoadAsset<GameObject>("ToilSlayerController"); MantiToilControllerPrefab = val.LoadAsset<GameObject>("MantiToilController"); MantiSlayerControllerPrefab = val.LoadAsset<GameObject>("MantiSlayerController"); ToilMaskedControllerPrefab = val.LoadAsset<GameObject>("ToilMaskedController"); SlayerMaskedControllerPrefab = val.LoadAsset<GameObject>("SlayerMaskedController"); ToilHeadPlush = val.LoadAsset<Item>("ToilHeadPlush"); ToilSlayerPlush = val.LoadAsset<Item>("ToilSlayerPlush"); Plugin.logger.LogInfo((object)"Successfully loaded assets from AssetBundle!"); } catch (Exception arg) { Plugin.logger.LogError((object)$"Error: Failed to load assets from AssetBundle.\n\n{arg}"); } } } public class ExtendedConfigEntry<T> { public ConfigEntry<T> ConfigEntry; public Func<T> GetValue; public Action<T> SetValue; public bool UseEnableConfiguration = true; public T DefaultValue => (T)((ConfigEntryBase)ConfigEntry).DefaultValue; public T Value { get { return GetValue(); } set { SetValue(value); } } public ExtendedConfigEntry(string section, string key, T defaultValue, string description, bool useEnableConfiguration = true) { ConfigEntry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, description); UseEnableConfiguration = useEnableConfiguration; Initialize(); } public ExtendedConfigEntry(string section, string key, T defaultValue, ConfigDescription configDescription = null, bool useEnableConfiguration = true) { ConfigEntry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, configDescription); UseEnableConfiguration = useEnableConfiguration; Initialize(); } private void Initialize() { if (GetValue == null) { GetValue = () => (UseEnableConfiguration && !Plugin.ConfigManager.EnableConfiguration.Value) ? DefaultValue : ConfigEntry.Value; } if (SetValue == null) { SetValue = delegate(T value) { ConfigEntry.Value = value; }; } } public void ResetToDefault() { ConfigEntry.Value = (T)((ConfigEntryBase)ConfigEntry).DefaultValue; } } internal static class NetworkUtils { public static bool IsServer { get { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } return NetworkManager.Singleton.IsServer; } } public static bool IsHost { get { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } return NetworkManager.Singleton.IsHost; } } public static ulong GetLocalClientId() { return NetworkManager.Singleton.LocalClientId; } public static bool IsLocalClientId(ulong clientId) { return clientId == GetLocalClientId(); } } internal static class PlayerUtils { public static bool IsLocalPlayer(PlayerControllerB playerScript) { return (Object)(object)playerScript == (Object)(object)GetLocalPlayerScript(); } public static int GetPlayerId(PlayerControllerB playerScript) { return (int)playerScript.playerClientId; } public static int GetLocalPlayerId() { return (int)GetLocalPlayerScript().playerClientId; } public static PlayerControllerB GetPlayerScript(int playerId) { try { return StartOfRound.Instance.allPlayerScripts[playerId]; } catch { return null; } } public static PlayerControllerB GetLocalPlayerScript() { return GameNetworkManager.Instance.localPlayerController; } } [BepInPlugin("com.github.zehsteam.ToilHead", "ToilHead", "1.9.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class Plugin : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("com.github.zehsteam.ToilHead"); internal static Plugin Instance; internal static ManualLogSource logger; internal static SyncedConfigManager ConfigManager; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } logger = Logger.CreateLogSource("com.github.zehsteam.ToilHead"); logger.LogInfo((object)"ToilHead has awoken!"); harmony.PatchAll(typeof(GameNetworkManagerPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); harmony.PatchAll(typeof(RoundManagerPatch)); harmony.PatchAll(typeof(TerminalPatch)); harmony.PatchAll(typeof(PlayerControllerBPatch)); harmony.PatchAll(typeof(RagdollGrabbableObjectPatch)); harmony.PatchAll(typeof(EnemyAIPatch)); harmony.PatchAll(typeof(SpringManAIPatch)); harmony.PatchAll(typeof(MaskedPlayerEnemyPatch)); harmony.PatchAll(typeof(TurretPatch)); ConfigManager = new SyncedConfigManager(); Content.Load(); TurretHeadManager.Initialize(); RegisterScrapItems(); NetcodePatcherAwake(); } private void NetcodePatcherAwake() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { 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 void OnLocalDisconnect() { logger.LogInfo((object)"Local player disconnected. Removing hostConfigData."); ConfigManager.SetHostConfigData(null); TurretHeadManager.Reset(); } public void OnNewLevelLoaded() { Secret.SpawnSecrets(); } public void OnNewLevelFinishedLoading() { TurretHeadManager.TrySetPlayerTurretHeadsOnServer(); } public void OnShipHasLeft() { TurretHeadManager.Reset(); } private void RegisterScrapItems() { if (!LethalLibProxy.HasMod || !MonsterPlushiesProxy.HasMod) { return; } try { ScrapHelper.RegisterScrap(Content.ToilHeadPlush, ConfigManager.ToilHeadPlushieSpawnWeight.Value, ConfigManager.ToilHeadPlushieSpawnAllMoons.Value, ConfigManager.ToilHeadPlushieMoonSpawnList.Value, twoHanded: false, ConfigManager.ToilHeadPlushieCarryWeight.Value, ConfigManager.ToilHeadPlushieMinValue.Value, ConfigManager.ToilHeadPlushieMaxValue.Value); ScrapHelper.RegisterScrap(Content.ToilSlayerPlush, ConfigManager.ToilSlayerPlushieSpawnWeight.Value, ConfigManager.ToilSlayerPlushieSpawnAllMoons.Value, ConfigManager.ToilSlayerPlushieMoonSpawnList.Value, twoHanded: false, ConfigManager.ToilSlayerPlushieCarryWeight.Value, ConfigManager.ToilSlayerPlushieMinValue.Value, ConfigManager.ToilSlayerPlushieMaxValue.Value); } catch (Exception arg) { logger.LogWarning((object)$"Warning: Failed to register scrap items.\n\n{arg}"); } } public void LogInfoExtended(object data) { if (ConfigManager.ExtendedLogging.Value) { logger.LogInfo(data); } } public void LogWarningExtended(object data) { if (ConfigManager.ExtendedLogging.Value) { logger.LogWarning(data); } } public void LogErrorExtended(object data) { if (ConfigManager.ExtendedLogging.Value) { logger.LogError(data); } } } internal static class ScrapHelper { public static void RegisterScrap(Item item, int iRarity, bool spawnAllMoons, string moonSpawnList, bool twoHanded, int carryWeight, int minValue, int maxValue) { if (!LethalLibProxy.HasMod) { return; } try { item.twoHanded = twoHanded; item.weight = (float)carryWeight / 105f + 1f; item.minValue = minValue; item.maxValue = maxValue; Utilities.FixMixerGroups(item.spawnPrefab); NetworkPrefabs.RegisterNetworkPrefab(item.spawnPrefab); if (spawnAllMoons) { Items.RegisterScrap(item, iRarity, (LevelTypes)(-1)); Plugin.logger.LogInfo((object)$"Registered \"{item.itemName}\" scrap item with {iRarity} rarity."); } else { RegisterScrapForMoons(item, iRarity, moonSpawnList); } } catch (Exception arg) { Plugin.logger.LogError((object)$"Error: Failed to register \"{item.itemName}\" scrap item.\n\n{arg}"); } } private static void RegisterScrapForMoons(Item item, int iRarity, string moonSpawnList) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, LevelTypes> dictionary = new Dictionary<string, LevelTypes>(); dictionary.Add("Experimentation", (LevelTypes)4); dictionary.Add("Assurance", (LevelTypes)8); dictionary.Add("Vow", (LevelTypes)16); dictionary.Add("Offense", (LevelTypes)32); dictionary.Add("March", (LevelTypes)64); dictionary.Add("Adamance", (LevelTypes)2048); dictionary.Add("Rend", (LevelTypes)128); dictionary.Add("Dine", (LevelTypes)256); dictionary.Add("Titan", (LevelTypes)512); dictionary.Add("Artifice", (LevelTypes)4096); dictionary.Add("Embrion", (LevelTypes)8192); foreach (string item2 in from _ in moonSpawnList.Split(',') select GetFormattedSting(_.Trim())) { if (dictionary.TryGetValue(item2, out var value)) { Items.RegisterScrap(item, iRarity, value); Plugin.logger.LogInfo((object)$"Registered \"{item.itemName}\" scrap item on moon \"{item2}\" with {iRarity} rarity."); } } } private static string GetFormattedSting(string value) { if (value.Length <= 1) { return value.ToUpper(); } return value.Substring(0, 1).ToUpper() + value.Substring(1, value.Length - 1).ToLower(); } } internal static class Secret { public static void SpawnSecrets() { string planetName = StartOfRound.Instance.currentLevel.PlanetName; if (planetName == "57 Asteroid-13") { SpawnAsteroid13Secrets(); } } public static void SpawnAsteroid13Secrets() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_0125: 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_0131: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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_018d: 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_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: 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_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Content.TurretPropPrefab == (Object)null) { Plugin.Instance.LogWarningExtended("Warning: Failed to spawn Asteroid13 secrets. turretPropPrefab is null."); return; } Vector3 val = Content.TurretPropPrefab.transform.localScale * 1.3f; Vector3 positionOffset = default(Vector3); ((Vector3)(ref positionOffset))..ctor(0f, 3.031f, -0.464f); Vector3 rotationOffset = default(Vector3); ((Vector3)(ref rotationOffset))..ctor(-27.2f, 0f, 0f); Vector3 positionOffset2 = default(Vector3); ((Vector3)(ref positionOffset2))..ctor(0f, 3.105f, -0.11f); Vector3 zero = Vector3.zero; Vector3 positionOffset3 = default(Vector3); ((Vector3)(ref positionOffset3))..ctor(0f, 6.217f, -0.225f); Vector3 zero2 = Vector3.zero; SpawnTurretProp("coilheadstuck_model", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadrigged", positionOffset3, zero2, val * 2f); SpawnTurretProp("coilheadstuck_model (5)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (7)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (8)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (9)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (10)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (6)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (29)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (24)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (25)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (26)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (27)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (28)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (23)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (18)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (19)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (20)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (21)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadstuck_model (22)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (17)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (12)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (13)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (14)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (15)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_model (16)", positionOffset, rotationOffset, val); SpawnTurretProp("asteroid(Clone)/coilheadstuck_2_model (7)", positionOffset2, zero, val); SpawnTurretProp("coilheadstuck_2_model (1)", positionOffset2, zero, val); SpawnTurretProp("coilheadstuck_model (11)", positionOffset, rotationOffset, val); SpawnTurretProp("coilheadrigged (1)", positionOffset3, zero2, val * 2f); Plugin.Instance.LogInfoExtended("Spawned Asteroid13 secrets."); } private static void SpawnTurretProp(string parentName, Vector3 positionOffset, Vector3 rotationOffset) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) SpawnTurretProp(parentName, positionOffset, rotationOffset, Content.TurretPropPrefab.transform.localScale); } private static void SpawnTurretProp(string parentName, Vector3 positionOffset, Vector3 rotationOffset, Vector3 scale) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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) if ((Object)(object)Content.TurretPropPrefab == (Object)null) { Plugin.Instance.LogWarningExtended("Warning: Failed to Instantiate turretPropPrefab. turretPropPrefab is null."); return; } GameObject val = GameObject.Find(parentName); if ((Object)(object)val == (Object)null) { Plugin.Instance.LogWarningExtended("Warning: Failed to Instantiate turretPropPrefab. Parent GameObject is null."); return; } Transform transform = Object.Instantiate<GameObject>(Content.TurretPropPrefab, Vector3.zero, Quaternion.identity, val.transform).transform; transform.localScale = scale; transform.localRotation = Quaternion.identity; transform.Rotate(rotationOffset, (Space)1); transform.localPosition = positionOffset; Utils.DisableColliders(((Component)transform).gameObject); } } public class SpawnData { public int MaxSpawnCount; public float SpawnChance; public SpawnData(string value) { ParseValue(value); } protected virtual void ParseValue(string value) { string[] array = (from _ in value.Split(':') select _.Trim()).ToArray(); int num = 2; if (array.Length != num) { Plugin.logger.LogError((object)$"ParseValue Error: Invalid item length for string \"{value}\". Length is {array.Length} but should have been {num}."); return; } TryParseInt(array[0], out MaxSpawnCount); TryParseFloat(array[1], out SpawnChance); Plugin.Instance.LogInfoExtended($"Parsed SpawnData value string. MaxSpawnCount: {MaxSpawnCount}, SpawnChance: {SpawnChance}"); } protected bool TryParseInt(string value, out int parsedInt) { if (int.TryParse(value, out parsedInt)) { return true; } Plugin.logger.LogError((object)("TryParseItem Error: Failed to parse int from string \"" + value + "\".")); return false; } protected bool TryParseFloat(string value, out float parsedFloat) { if (float.TryParse(value, out parsedFloat)) { return true; } Plugin.logger.LogError((object)("TryParseItem Error: Failed to parse float from string \"" + value + "\".")); return false; } } public class MoonSpawnData : SpawnData { public string PlanetName; public MoonSpawnData(string value) : base(value) { } protected override void ParseValue(string value) { string[] array = (from _ in value.Split(':') select _.Trim()).ToArray(); int num = 3; if (array.Length != num) { Plugin.logger.LogError((object)$"ParseValue Error: Invalid item length for string \"{value}\". Length is {array.Length} but should have been {num}."); return; } PlanetName = array[0]; TryParseInt(array[1], out MaxSpawnCount); TryParseFloat(array[2], out SpawnChance); Plugin.Instance.LogInfoExtended($"Parsed MoonSpawnData value string. PlanetName: \"{PlanetName}\", MaxSpawnCount: {MaxSpawnCount}, SpawnChance: {SpawnChance}"); } } public class MoonSpawnDataList { public List<MoonSpawnData> List = new List<MoonSpawnData>(); public SpawnData DefaultSpawnData; public MoonSpawnDataList(string value) { ParseValue(value); } public MoonSpawnDataList(string value, SpawnData defaultSpawnData) { ParseValue(value); DefaultSpawnData = defaultSpawnData; } private void ParseValue(string value) { if (value == string.Empty) { return; } if (string.IsNullOrWhiteSpace(value)) { Plugin.logger.LogError((object)"ParseValue Error: MoonSpawnDataList value is null or whitespace."); return; } string[] array = (from _ in value.Split(',') select _.Trim()).ToArray(); List = new List<MoonSpawnData>(); string[] array2 = array; foreach (string value2 in array2) { List.Add(new MoonSpawnData(value2)); } } public SpawnData GetSpawnDataForCurrentMoon() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return DefaultSpawnData; } return GetSpawnDataForMoon(StartOfRound.Instance.currentLevel.PlanetName); } public SpawnData GetSpawnDataForMoon(string planetName) { foreach (MoonSpawnData item in List) { if (item.PlanetName == planetName) { return item; } } return DefaultSpawnData; } } [Serializable] public class SyncedConfigData : INetworkSerializable { public float TurretLostLOSDuration; public float TurretRotationRange; public float TurretCodeAccessCooldownDuration; public bool TurretDetectionRotation; public float TurretDetectionRotationSpeed; public float TurretChargingDuration; public float TurretChargingRotationSpeed; public float TurretFiringRotationSpeed; public float TurretBerserkDuration; public float TurretBerserkRotationSpeed; public SyncedConfigData() { } public SyncedConfigData(SyncedConfigManager configManager) { TurretLostLOSDuration = configManager.TurretLostLOSDuration.Value; TurretRotationRange = configManager.TurretRotationRange.Value; TurretCodeAccessCooldownDuration = configManager.TurretCodeAccessCooldownDuration.Value; TurretDetectionRotation = configManager.TurretDetectionRotation.Value; TurretDetectionRotationSpeed = configManager.TurretDetectionRotationSpeed.Value; TurretChargingDuration = configManager.TurretChargingDuration.Value; TurretChargingRotationSpeed = configManager.TurretChargingRotationSpeed.Value; TurretFiringRotationSpeed = configManager.TurretFiringRotationSpeed.Value; TurretBerserkDuration = configManager.TurretBerserkDuration.Value; TurretBerserkRotationSpeed = configManager.TurretBerserkRotationSpeed.Value; } public unsafe void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0062: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0094: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretLostLOSDuration, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretRotationRange, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretCodeAccessCooldownDuration, default(ForPrimitives)); ((BufferSerializer<bool>*)(&serializer))->SerializeValue<bool>(ref TurretDetectionRotation, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretDetectionRotationSpeed, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretChargingDuration, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretChargingRotationSpeed, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretFiringRotationSpeed, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretBerserkDuration, default(ForPrimitives)); ((BufferSerializer<float>*)(&serializer))->SerializeValue<float>(ref TurretBerserkRotationSpeed, default(ForPrimitives)); } } public class SyncedConfigManager { public SyncedConfigData HostConfigData { get; private set; } public ExtendedConfigEntry<bool> EnableConfiguration { get; private set; } public ExtendedConfigEntry<bool> ExtendedLogging { get; private set; } public ExtendedConfigEntry<string> ToilationToilPlayerSpawnSettings { get; private set; } public ExtendedConfigEntry<float> ToilationToilPlayerSlayerChance { get; private set; } public ExtendedConfigEntry<string> ToilationToilHeadSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilationToilSlayerSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilationMantiToilSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilationMantiSlayerSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilationToilMaskedSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilationSlayerMaskedSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilPlayerDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilPlayerSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<float> ToilPlayerSlayerChance { get; private set; } public ExtendedConfigEntry<bool> SpawnToiledPlayerRagdolls { get; private set; } public ExtendedConfigEntry<bool> SpawnRealToiledPlayerRagdolls { get; private set; } public ExtendedConfigEntry<string> ToilHeadDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilHeadSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<string> MantiToilDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> MantiToilSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<string> ToilSlayerDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilSlayerSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<string> MantiSlayerDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> MantiSlayerSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<string> ToilMaskedDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> ToilMaskedSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<string> SlayerMaskedDefaultSpawnSettings { get; private set; } public ExtendedConfigEntry<string> SlayerMaskedSpawnSettingsMoonList { get; private set; } public ExtendedConfigEntry<int> ToilHeadPlushieSpawnWeight { get; private set; } public ExtendedConfigEntry<bool> ToilHeadPlushieSpawnAllMoons { get; private set; } public ExtendedConfigEntry<string> ToilHeadPlushieMoonSpawnList { get; private set; } public ExtendedConfigEntry<int> ToilHeadPlushieCarryWeight { get; private set; } public ExtendedConfigEntry<int> ToilHeadPlushieMinValue { get; private set; } public ExtendedConfigEntry<int> ToilHeadPlushieMaxValue { get; private set; } public ExtendedConfigEntry<int> ToilSlayerPlushieSpawnWeight { get; private set; } public ExtendedConfigEntry<bool> ToilSlayerPlushieSpawnAllMoons { get; private set; } public ExtendedConfigEntry<string> ToilSlayerPlushieMoonSpawnList { get; private set; } public ExtendedConfigEntry<int> ToilSlayerPlushieCarryWeight { get; private set; } public ExtendedConfigEntry<int> ToilSlayerPlushieMinValue { get; private set; } public ExtendedConfigEntry<int> ToilSlayerPlushieMaxValue { get; private set; } public ExtendedConfigEntry<float> TurretLostLOSDuration { get; private set; } public ExtendedConfigEntry<float> TurretRotationRange { get; private set; } public ExtendedConfigEntry<float> TurretCodeAccessCooldownDuration { get; private set; } public ExtendedConfigEntry<bool> TurretDetectionRotation { get; private set; } public ExtendedConfigEntry<float> TurretDetectionRotationSpeed { get; private set; } public ExtendedConfigEntry<float> TurretChargingDuration { get; private set; } public ExtendedConfigEntry<float> TurretChargingRotationSpeed { get; private set; } public ExtendedConfigEntry<float> TurretFiringRotationSpeed { get; private set; } public ExtendedConfigEntry<float> TurretBerserkDuration { get; private set; } public ExtendedConfigEntry<float> TurretBerserkRotationSpeed { get; private set; } public SyncedConfigManager() { BindConfigs(); ClearUnusedEntries(); } private void BindConfigs() { EnableConfiguration = new ExtendedConfigEntry<bool>("General Settings", "EnableConfiguration", defaultValue: false, "Enable if you want to use custom set config setting values. If disabled, the default config setting values will be used.", useEnableConfiguration: false); ExtendedLogging = new ExtendedConfigEntry<bool>("General Settings", "ExtendedLogging", defaultValue: false, "Enable extended logging.", useEnableConfiguration: false); ToilationToilPlayerSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilPlayerSpawnSettings", "1:7", GetDescriptionForMoonSpawnSettings("Toil-Player", "69-Toilation")); ToilationToilPlayerSlayerChance = new ExtendedConfigEntry<float>("Toilation Settings", "ToilPlayerSlayerChance", 20f, "The percent chance a Toil-Player will become a Slayer-Player for 69-Toilation."); ToilationToilHeadSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilHeadSpawnSettings", "6:75", GetDescriptionForMoonSpawnSettings("Toil-Head", "69-Toilation")); ToilationMantiToilSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "MantiToilSpawnSettings", "50:90", GetDescriptionForMoonSpawnSettings("Manti-Toil", "69-Toilation")); ToilationToilSlayerSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilSlayerSpawnSettings", "2:10", GetDescriptionForMoonSpawnSettings("Toil-Slayer", "69-Toilation")); ToilationMantiSlayerSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "MantiSlayerSpawnSettings", "2:20", GetDescriptionForMoonSpawnSettings("Manti-Slayer", "69-Toilation")); ToilationToilMaskedSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "ToilMaskedSpawnSettings", "2:15", GetDescriptionForMoonSpawnSettings("Toil-Masked", "69-Toilation")); ToilationSlayerMaskedSpawnSettings = new ExtendedConfigEntry<string>("Toilation Settings", "SlayerMaskedSpawnSettings", "1:5", GetDescriptionForMoonSpawnSettings("Slayer-Masked", "69-Toilation")); ToilPlayerDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Player Settings", "ToilPlayerDefaultSpawnSettings", "1:3", GetDescriptionForDefaultSpawnSettings("Toil-Player")); string defaultValue = "85 Rend:1:4, 7 Dine:1:4, 8 Titan:1:5, 68 Artifice:1:5, 57 Asteroid-13:1:5, 523 Ooblterra:1:6"; ToilPlayerSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Player Settings", "ToilPlayerSpawnSettingsMoonList", defaultValue, GetDescriptionForMoonSpawnSettingsList("Toil-Player")); ToilPlayerSlayerChance = new ExtendedConfigEntry<float>("Toil-Player Settings", "ToilPlayerSlayerChance", 10f, "The percent chance a Toil-Player will become a Slayer-Player."); SpawnToiledPlayerRagdolls = new ExtendedConfigEntry<bool>("Player Ragdoll Settings", "SpawnToiledPlayerRagdolls", defaultValue: true, "If enabled, will spawn a Toiled player ragdoll when a player dies to a Turret-Head in any way."); SpawnRealToiledPlayerRagdolls = new ExtendedConfigEntry<bool>("Player Ragdoll Settings", "SpawnRealToiledPlayerRagdolls", defaultValue: true, "If enabled, will spawn a real turret on the Toiled player ragdoll."); ToilHeadDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Head Settings", "ToilHeadDefaultSpawnSettings", "1:30", GetDescriptionForDefaultSpawnSettings("Toil-Head")); string defaultValue2 = "41 Experimentation:1:10, 220 Assurance:1:20, 56 Vow:1:20, 21 Offense:1:20, 61 March:1:20, 20 Adamance:1:30, 85 Rend:1:40, 7 Dine:1:45, 8 Titan:1:50, 68 Artifice:2:70, 5 Embrion:1:30, 57 Asteroid-13:2:30, 523 Ooblterra:2:70"; ToilHeadSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Head Settings", "ToilHeadSpawnSettingsMoonList", defaultValue2, GetDescriptionForMoonSpawnSettingsList("Toil-Head")); MantiToilDefaultSpawnSettings = new ExtendedConfigEntry<string>("Manti-Toil Settings", "MantiToilDefaultSpawnSettings", "5:50", GetDescriptionForDefaultSpawnSettings("Manti-Toil")); string defaultValue3 = "20 Adamance:5:60, 85 Rend:5:60, 7 Dine:5:65, 8 Titan:5:70, 68 Artifice:8:75"; MantiToilSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Manti-Toil Settings", "MantiToilSpawnSettingsMoonList", defaultValue3, GetDescriptionForMoonSpawnSettingsList("Manti-Toil")); ToilSlayerDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Slayer Settings", "ToilSlayerDefaultSpawnSettings", "1:10", GetDescriptionForDefaultSpawnSettings("Toil-Slayer")); string defaultValue4 = "20 Adamance:1:15, 85 Rend:1:15, 7 Dine:1:15, 8 Titan:1:20, 68 Artifice:1:20, 57 Asteroid-13:1:15, 523 Ooblterra:1:25"; ToilSlayerSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Slayer Settings", "ToilSlayerSpawnSettingsMoonList", defaultValue4, GetDescriptionForMoonSpawnSettingsList("Toil-Slayer")); MantiSlayerDefaultSpawnSettings = new ExtendedConfigEntry<string>("Manti-Slayer Settings", "MantiSlayerDefaultSpawnSettings", "1:10", GetDescriptionForDefaultSpawnSettings("Manti-Slayer")); string defaultValue5 = "20 Adamance:1:15, 85 Rend:1:15, 7 Dine:1:15, 8 Titan:1:20, 68 Artifice:1:20, 57 Asteroid-13:1:15, 523 Ooblterra:1:25"; MantiSlayerSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Manti-Slayer Settings", "MantiSlayerSpawnSettingsMoonList", defaultValue5, GetDescriptionForMoonSpawnSettingsList("Manti-Slayer")); ToilMaskedDefaultSpawnSettings = new ExtendedConfigEntry<string>("Toil-Masked Settings", "ToilMaskedDefaultSpawnSettings", "1:10", GetDescriptionForDefaultSpawnSettings("Toil-Masked")); string defaultValue6 = ""; ToilMaskedSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Toil-Masked Settings", "ToilMaskedSpawnSettingsMoonList", defaultValue6, GetDescriptionForMoonSpawnSettingsList("Toil-Masked")); SlayerMaskedDefaultSpawnSettings = new ExtendedConfigEntry<string>("Slayer-Masked Settings", "SlayerMaskedDefaultSpawnSettings", "1:5", GetDescriptionForDefaultSpawnSettings("Slayer-Masked")); string defaultValue7 = ""; SlayerMaskedSpawnSettingsMoonList = new ExtendedConfigEntry<string>("Slayer-Masked Settings", "SlayerMaskedSpawnSettingsMoonList", defaultValue7, GetDescriptionForMoonSpawnSettingsList("Slayer-Masked")); ToilHeadPlushieSpawnWeight = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "SpawnWeight", 10, "Toil-Head plushie spawn chance weight."); ToilHeadPlushieSpawnAllMoons = new ExtendedConfigEntry<bool>("Toil-Head Plushie Settings", "SpawnAllMoons", defaultValue: true, "If true, the Toil-Head plushie will spawn on all moons. If false, the Toil-Head plushie will only spawn on moons set in the moons list."); ToilHeadPlushieMoonSpawnList = new ExtendedConfigEntry<string>("Toil-Head Plushie Settings", "MoonSpawnList", "Experimentation, Assurance, Vow, Offense, March, Adamance, Rend, Dine, Titan, Artifice, Embrion", "The list of moons the Toil-Head plushie will spawn on.\nCurrently only works for vanilla moons.\nOnly works if PlushieSpawnAllMoons is false."); ToilHeadPlushieCarryWeight = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "CarryWeight", 6, "Toil-Head plushie carry weight in pounds."); ToilHeadPlushieMinValue = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "MinValue", 80, "Toil-Head plushie min scrap value."); ToilHeadPlushieMaxValue = new ExtendedConfigEntry<int>("Toil-Head Plushie Settings", "MaxValue", 250, "Toil-Head plushie max scrap value."); ToilSlayerPlushieSpawnWeight = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "SpawnWeight", 5, "Toil-Slayer plushie spawn chance weight."); ToilSlayerPlushieSpawnAllMoons = new ExtendedConfigEntry<bool>("Toil-Slayer Plushie Settings", "SpawnAllMoons", defaultValue: true, "If true, the Toil-Slayer plushie will spawn on all moons. If false, the Toil-Slayer plushie will only spawn on moons set in the moons list."); ToilSlayerPlushieMoonSpawnList = new ExtendedConfigEntry<string>("Toil-Slayer Plushie Settings", "MoonSpawnList", "Experimentation, Assurance, Vow, Offense, March, Adamance, Rend, Dine, Titan, Artifice, Embrion", "The list of moons the Toil-Slayer plushie will spawn on.\nCurrently only works for vanilla moons.\nOnly works if PlushieSpawnAllMoons is false."); ToilSlayerPlushieCarryWeight = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "CarryWeight", 12, "Toil-Slayer plushie carry weight in pounds."); ToilSlayerPlushieMinValue = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "MinValue", 150, "Toil-Slayer plushie min scrap value."); ToilSlayerPlushieMaxValue = new ExtendedConfigEntry<int>("Toil-Slayer Plushie Settings", "MaxValue", 380, "Toil-Slayer plushie max scrap value."); TurretLostLOSDuration = new ExtendedConfigEntry<float>("Turret Settings", "LostLOSDuration", 0.75f, "The duration until the turret loses the target player when not in line of sight.\nVanilla Turret Default value: 2"); TurretLostLOSDuration.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretLostLOSDuration : TurretLostLOSDuration.ConfigEntry.Value; TurretRotationRange = new ExtendedConfigEntry<float>("Turret Settings", "RotationRange", 75f, "The rotation range of the turret in degrees.\nVanilla Turret Default value: 75"); TurretRotationRange.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretRotationRange : TurretRotationRange.ConfigEntry.Value; TurretCodeAccessCooldownDuration = new ExtendedConfigEntry<float>("Turret Settings", "CodeAccessCooldownDuration", 7f, "The duration of the turret being disabled from the terminal in seconds.\nVanilla Turret Default value: 7"); TurretCodeAccessCooldownDuration.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretCodeAccessCooldownDuration : TurretCodeAccessCooldownDuration.ConfigEntry.Value; TurretDetectionRotation = new ExtendedConfigEntry<bool>("Turret Detection Settings", "Rotation", defaultValue: false, "If enabled, the turret will rotate when searching for players.\nVanilla Turret Default value: true"); TurretDetectionRotation.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretDetectionRotation : TurretDetectionRotation.ConfigEntry.Value; TurretDetectionRotationSpeed = new ExtendedConfigEntry<float>("Turret Detection Settings", "RotationSpeed", 28f, "The rotation speed of the turret when in detection state.\nVanilla Turret Default value: 28"); TurretDetectionRotationSpeed.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretDetectionRotationSpeed : TurretDetectionRotationSpeed.ConfigEntry.Value; TurretChargingDuration = new ExtendedConfigEntry<float>("Turret Charging Settings", "ChargingDuration", 2f, "The duration of the turret charging state.\nVanilla Turret Default value: 1.5"); TurretChargingDuration.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretChargingDuration : TurretChargingDuration.ConfigEntry.Value; TurretChargingRotationSpeed = new ExtendedConfigEntry<float>("Turret Charging Settings", "RotationSpeed", 95f, "The rotation speed of the turret when in charging state.\nVanilla Turret Default value: 95"); TurretChargingRotationSpeed.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretChargingRotationSpeed : TurretChargingRotationSpeed.ConfigEntry.Value; TurretFiringRotationSpeed = new ExtendedConfigEntry<float>("Turret Firing Settings", "RotationSpeed", 95f, "The rotation speed of the turret when in firing state.\nVanilla Turret Default value: 95"); TurretFiringRotationSpeed.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretFiringRotationSpeed : TurretFiringRotationSpeed.ConfigEntry.Value; TurretBerserkDuration = new ExtendedConfigEntry<float>("Turret Berserk Settings", "BerserkDuration", 9f, "The duration of the turret berserk state.\nVanilla Turret Default value: 9"); TurretBerserkDuration.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretBerserkDuration : TurretBerserkDuration.ConfigEntry.Value; TurretBerserkRotationSpeed = new ExtendedConfigEntry<float>("Turret Berserk Settings", "RotationSpeed", 77f, "The rotation speed of the turret when in berserk state.\nVanilla Turret Default value: 77"); TurretBerserkRotationSpeed.GetValue = () => (HostConfigData != null) ? HostConfigData.TurretBerserkRotationSpeed : TurretBerserkRotationSpeed.ConfigEntry.Value; } private string GetDescriptionForSpawnSettings(string enemyName) { string text = enemyName + " spawn settings.\n"; text += "MaxSpawnCount,SpawnChance\n"; return text + "<int>,<float>"; } private string GetDescriptionForMoonSpawnSettings(string enemyName, string planetName) { string text = enemyName + " spawn settings for " + planetName + ".\n"; text += "MaxSpawnCount,SpawnChance\n"; return text + "<int>,<float>"; } private string GetDescriptionForMoonSpawnSettingsList(string enemyName) { string text = enemyName + " spawn settings list for moons.\n"; text += "Separate each entry with a comma.\n"; text += "PlanetName:MaxSpawnCount:SpawnChance\n"; return text + "<string>:<int>:<float>"; } private string GetDescriptionForDefaultSpawnSettings(string enemyName) { string text = enemyName + " default spawn settings for all moons.\n"; text += "MaxSpawnCount:SpawnChance\n"; return text + "<int>:<float>"; } private void ClearUnusedEntries() { ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config; PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic); Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null); dictionary.Clear(); config.Save(); } internal void SetHostConfigData(SyncedConfigData syncedConfigData) { HostConfigData = syncedConfigData; } private void SyncedConfigsChanged() { //IL_0015: 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) if (NetworkUtils.IsServer) { PluginNetworkBehaviour.Instance.SendConfigToPlayerClientRpc(new SyncedConfigData(this)); } } } public class TurretHeadData { public bool ForceSpawns; public int ForceMaxSpawnCount = -1; public string EnemyName { get; private set; } public bool IsSlayer { get; private set; } public GameObject ControllerPrefab { get; private set; } public MoonSpawnDataList MoonSpawnDataList { get; private set; } public SpawnData ToilationSpawnData { get; private set; } public int SpawnCount { get; private set; } public TurretHeadData(string enemyName, bool isSlayer, GameObject controllerPrefab, MoonSpawnDataList moonSpawnDataList, SpawnData toilationSpawnData) { EnemyName = enemyName; IsSlayer = isSlayer; ControllerPrefab = controllerPrefab; MoonSpawnDataList = moonSpawnDataList; ToilationSpawnData = toilationSpawnData; } public void Reset() { SpawnCount = 0; ForceSpawns = false; ForceMaxSpawnCount = -1; } public void AddToSpawnCount() { SpawnCount++; } public SpawnData GetSpawnDataForCurrentMoon() { if (Utils.IsCurrentMoonToilation()) { return ToilationSpawnData; } return MoonSpawnDataList.GetSpawnDataForCurrentMoon(); } } public static class TurretHeadManager { [CompilerGenerated] private sealed class <>c__DisplayClass30_0 { public PlayerControllerB playerScript; public GameObject ragdollObject; internal bool <SetDeadBodyTurretHeadOnServerCO>b__0() { return (Object)(object)playerScript.deadBody != (Object)null; } internal bool <SetDeadBodyTurretHeadOnServerCO>b__1() { return (Object)(object)ragdollObject.GetComponentInChildren<NetworkObject>() != (Object)null; } } [CompilerGenerated] private sealed class <SetDeadBodyTurretHeadOnServerCO>d__30 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB playerScript; private <>c__DisplayClass30_0 <>8__1; public bool isSlayer; public bool isReal; private string <playerUsername>5__2; private DeadBodyInfo <deadBodyScript>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SetDeadBodyTurretHeadOnServerCO>d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <playerUsername>5__2 = null; <deadBodyScript>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass30_0(); <>8__1.playerScript = playerScript; if (!NetworkUtils.IsServer) { return false; } <playerUsername>5__2 = <>8__1.playerScript.playerUsername; <>2__current = Utils.WaitUntil(() => (Object)(object)<>8__1.playerScript.deadBody != (Object)null); <>1__state = 1; return true; case 1: <>1__state = -1; <deadBodyScript>5__3 = <>8__1.playerScript.deadBody; if ((Object)(object)<deadBodyScript>5__3 == (Object)null) { Plugin.logger.LogError((object)$"Error: Failed to set player \"{<playerUsername>5__2}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. DeadBodyInfo is null."); return false; } <>8__1.ragdollObject = ((Component)<deadBodyScript>5__3).gameObject; if (((Object)<>8__1.ragdollObject).name != "PlayerRagdollSpring Variant(Clone)") { Plugin.logger.LogError((object)$"Error: Failed to set player \"{<playerUsername>5__2}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. Player ragdoll is not of type \"PlayerRagdollSpring Variant\"."); return false; } <>2__current = Utils.WaitUntil(() => (Object)(object)<>8__1.ragdollObject.GetComponentInChildren<NetworkObject>() != (Object)null); <>1__state = 2; return true; case 2: { <>1__state = -1; NetworkObject componentInChildren = <>8__1.ragdollObject.GetComponentInChildren<NetworkObject>(); if ((Object)(object)componentInChildren == (Object)null) { Plugin.logger.LogError((object)$"Error: Failed to set player \"{<playerUsername>5__2}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. NetworkObject is null."); return false; } if (Utils.IsTurretHead(<deadBodyScript>5__3)) { Plugin.logger.LogError((object)$"Error: Failed to set player \"{<playerUsername>5__2}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server. Player is already a player ragdoll Turret-Head."); return false; } GameObject controllerPrefab = (isSlayer ? Content.SlayedDeadBodyControllerPrefab : Content.ToiledDeadBodyControllerPrefab); SpawnTurretHeadControllerOnServer(controllerPrefab, ((Component)componentInChildren).transform); Plugin.Instance.LogInfoExtended($"Set player \"{<playerUsername>5__2}\" ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {isReal}) on server."); 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(); } } private static Coroutine _setDeadBodyTurretHeadOnServerCoroutine; public static List<TurretHeadData> TurretHeadDataList { get; private set; } = new List<TurretHeadData>(); public static TurretHeadData PlayerTurretHeadData { get; private set; } public static Dictionary<EnemyAI, TurretHeadControllerBehaviour> EnemyTurretHeadControllerPairs { get; private set; } = new Dictionary<EnemyAI, TurretHeadControllerBehaviour>(); public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> PlayerTurretHeadControllerPairs { get; private set; } = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>(); public static Dictionary<PlayerControllerB, TurretHeadControllerBehaviour> DeadBodyTurretHeadControllerPairs { get; private set; } = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>(); internal static void Initialize() { TurretHeadDataList = new List<TurretHeadData>(6) { new TurretHeadData("Spring", isSlayer: false, Content.ToilHeadControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.ToilHeadSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilHeadDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilHeadSpawnSettings.Value)), new TurretHeadData("Spring", isSlayer: true, Content.ToilSlayerControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.ToilSlayerSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilSlayerDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilSlayerSpawnSettings.Value)), new TurretHeadData("Manticoil", isSlayer: false, Content.MantiToilControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.MantiToilSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.MantiToilDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationMantiToilSpawnSettings.Value)), new TurretHeadData("Manticoil", isSlayer: true, Content.MantiSlayerControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.MantiSlayerSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.MantiSlayerDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationMantiSlayerSpawnSettings.Value)), new TurretHeadData("Masked", isSlayer: false, Content.ToilMaskedControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.ToilMaskedSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilMaskedDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilMaskedSpawnSettings.Value)), new TurretHeadData("Masked", isSlayer: true, Content.SlayerMaskedControllerPrefab, new MoonSpawnDataList(Plugin.ConfigManager.SlayerMaskedSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.SlayerMaskedDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationSlayerMaskedSpawnSettings.Value)) }; PlayerTurretHeadData = new TurretHeadData(string.Empty, isSlayer: false, null, new MoonSpawnDataList(Plugin.ConfigManager.ToilPlayerSpawnSettingsMoonList.Value, new SpawnData(Plugin.ConfigManager.ToilPlayerDefaultSpawnSettings.Value)), new SpawnData(Plugin.ConfigManager.ToilationToilPlayerSpawnSettings.Value)); EnemyTurretHeadControllerPairs = new Dictionary<EnemyAI, TurretHeadControllerBehaviour>(); PlayerTurretHeadControllerPairs = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>(); DeadBodyTurretHeadControllerPairs = new Dictionary<PlayerControllerB, TurretHeadControllerBehaviour>(); _setDeadBodyTurretHeadOnServerCoroutine = null; } internal static void Reset() { TurretHeadDataList.ForEach(delegate(TurretHeadData _) { _.Reset(); }); PlayerTurretHeadData.Reset(); EnemyTurretHeadControllerPairs.Clear(); PlayerTurretHeadControllerPairs.Clear(); DeadBodyTurretHeadControllerPairs.Clear(); _setDeadBodyTurretHeadOnServerCoroutine = null; DespawnAllControllersOnServer(); } internal static bool TrySetEnemyTurretHeadOnServer(EnemyAI enemyScript, bool isSlayer) { if (!NetworkUtils.IsServer) { return false; } string enemyName = enemyScript.enemyType.enemyName; TurretHeadData enemyTurretHeadData = GetEnemyTurretHeadData(enemyName, isSlayer); if (enemyTurretHeadData == null) { Plugin.logger.LogError((object)("Error: Failed to try set \"" + enemyName + "\" Turret-Head on server. TurretHeadData is null.")); return false; } SpawnData spawnDataForCurrentMoon = enemyTurretHeadData.GetSpawnDataForCurrentMoon(); int num = spawnDataForCurrentMoon.MaxSpawnCount; if (enemyTurretHeadData.ForceMaxSpawnCount > -1) { num = enemyTurretHeadData.ForceMaxSpawnCount; } if (!enemyTurretHeadData.ForceSpawns) { if (enemyTurretHeadData.SpawnCount >= num) { return false; } if (!Utils.RandomPercent(spawnDataForCurrentMoon.SpawnChance)) { return false; } } return SetEnemyTurretHeadOnServer(enemyScript, isSlayer); } internal static void TrySetPlayerTurretHeadsOnServer() { if (!NetworkUtils.IsServer || !StartOfRound.Instance.currentLevel.spawnEnemiesAndScrap || GameNetworkManager.Instance.connectedPlayers == 1) { return; } List<PlayerControllerB> list = StartOfRound.Instance.allPlayerScripts.ToList(); for (int num = list.Count - 1; num >= 0; num--) { int index = Random.Range(0, num); bool isSlayer = Utils.RandomPercent(Plugin.ConfigManager.ToilPlayerSlayerChance.Value); PlayerControllerB val = list[index]; if (((Component)val).gameObject.activeSelf && val.isPlayerControlled) { TrySetPlayerTurretHeadOnServer(val, isSlayer); list.RemoveAt(index); } } } internal static bool TrySetPlayerTurretHeadOnServer(PlayerControllerB playerScript, bool isSlayer) { if (!NetworkUtils.IsServer) { return false; } TurretHeadData playerTurretHeadData = PlayerTurretHeadData; SpawnData spawnDataForCurrentMoon = playerTurretHeadData.GetSpawnDataForCurrentMoon(); int num = spawnDataForCurrentMoon.MaxSpawnCount; if (playerTurretHeadData.ForceMaxSpawnCount > -1) { num = playerTurretHeadData.ForceMaxSpawnCount; } if (!playerTurretHeadData.ForceSpawns) { if (playerTurretHeadData.SpawnCount >= num) { return false; } if (!Utils.RandomPercent(spawnDataForCurrentMoon.SpawnChance)) { return false; } } return SetPlayerTurretHeadOnServer(playerScript, isSlayer); } public static bool SetEnemyTurretHeadOnServer(EnemyAI enemyScript, bool isSlayer) { if (!NetworkUtils.IsServer) { return false; } if ((Object)(object)enemyScript == (Object)null) { Plugin.logger.LogError((object)$"Error: Failed to set enemy Turret-Head (isSlayer? {isSlayer}) on server. EnemyAI is null."); return false; } string enemyName = enemyScript.enemyType.enemyName; if (enemyScript.isEnemyDead) { Plugin.logger.LogError((object)$"Error: Failed to set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server. Enemy is already dead."); return false; } if (Utils.IsTurretHead(enemyScript)) { Plugin.logger.LogError((object)$"Error: Failed to set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server. Enemy is already a Turret-Head."); return false; } TurretHeadData enemyTurretHeadData = GetEnemyTurretHeadData(enemyName, isSlayer); if (enemyTurretHeadData == null) { Plugin.logger.LogError((object)$"Error: Failed to set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server. TurretHeadData is null."); return false; } SpawnTurretHeadControllerOnServer(enemyTurretHeadData.ControllerPrefab, ((Component)enemyScript).transform); Plugin.Instance.LogInfoExtended($"Set enemy \"{enemyName}\" Turret-Head (isSlayer? {isSlayer}) on server."); return true; } public static bool SetPlayerTurretHeadOnServer(PlayerControllerB playerScript, bool isSlayer) { if (!NetworkUtils.IsServer) { return false; } string playerUsername = playerScript.playerUsername; if ((Object)(object)playerScript == (Object)null) { Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server. PlayerControllerB is null."); return false; } if (playerScript.isPlayerDead) { Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server. Player is already dead."); return false; } if (Utils.IsTurretHead(playerScript)) { Plugin.logger.LogError((object)$"Error: Failed to set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server. Player is already a Turret-Head."); return false; } GameObject controllerPrefab = (isSlayer ? Content.SlayerPlayerControllerPrefab : Content.ToilPlayerControllerPrefab); SpawnTurretHeadControllerOnServer(controllerPrefab, ((Component)playerScript).transform); Plugin.Instance.LogInfoExtended($"Set player \"{playerUsername}\" Turret-Head (isSlayer? {isSlayer}) on server."); return true; } public static void SetDeadBodyTurretHead(PlayerControllerB playerScript, bool isSlayer) { if (NetworkUtils.IsServer) { SetDeadBodyTurretHeadOnServer(playerScript, isSlayer); } else { PluginNetworkBehaviour.Instance.SetToilHeadPlayerRagdollServerRpc(PlayerUtils.GetPlayerId(playerScript), isSlayer); } } public static void SetDeadBodyTurretHeadOnServer(PlayerControllerB playerScript, bool isSlayer) { if (!NetworkUtils.IsServer) { return; } bool value = Plugin.ConfigManager.SpawnRealToiledPlayerRagdolls.Value; if (!Plugin.ConfigManager.SpawnToiledPlayerRagdolls.Value) { Plugin.Instance.LogErrorExtended($"Error: Failed to set player ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {value}) on server. Spawning player ragdoll Turret-Heads is disabled in the config settings."); return; } if ((Object)(object)playerScript == (Object)null) { Plugin.logger.LogError((object)$"Error: Failed to set player ragdoll Turret-Head (isSlayer? {isSlayer}, isReal? {value}) on server. PlayerControllerB is null."); return; } if (_setDeadBodyTurretHeadOnServerCoroutine != null) { ((MonoBehaviour)StartOfRound.Instance).StopCoroutine(_setDeadBodyTurretHeadOnServerCoroutine); } _setDeadBodyTurretHeadOnServerCoroutine = ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(SetDeadBodyTurretHeadOnServerCO(playerScript, isSlayer, value)); } [IteratorStateMachine(typeof(<SetDeadBodyTurretHeadOnServerCO>d__30))] private static IEnumerator SetDeadBodyTurretHeadOnServerCO(PlayerControllerB playerScript, bool isSlayer, bool isReal) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SetDeadBodyTurretHeadOnServerCO>d__30(0) { playerScript = playerScript, isSlayer = isSlayer, isReal = isReal }; } private static void SpawnTurretHeadControllerOnServer(GameObject controllerPrefab, Transform parentTransform) { if (NetworkUtils.IsServer) { GameObject val = Object.Instantiate<GameObject>(controllerPrefab, parentTransform); val.GetComponent<NetworkObject>().Spawn(false); val.transform.SetParent(parentTransform); val.GetComponent<TurretHeadControllerBehaviour>().SetupTurret(); } } public static void AddEnemyTurretHeadControllerPair(EnemyAI enemyScript, TurretHeadControllerBehaviour behaviour) { EnemyTurretHeadControllerPairs.Add(enemyScript, behaviour); } public static void AddPlayerTurretHeadControllerPair(PlayerControllerB playerScript, TurretHeadControllerBehaviour behaviour) { PlayerTurretHeadControllerPairs.Add(playerScript, behaviour); } public static void AddDeadBodyTurretHeadControllerPair(PlayerControllerB playerScript, TurretHeadControllerBehaviour behaviour) { DeadBodyTurretHeadControllerPairs.Add(playerScript, behaviour); } internal static void AddToEnemySpawnCount(EnemyAI enemyScript, bool isSlayer) { string enemyName = enemyScript.enemyType.enemyName; TurretHeadData enemyTurretHeadData = GetEnemyTurretHeadData(enemyName, isSlayer); if (enemyTurretHeadData == null) { Plugin.logger.LogError((object)("Error: Failed to add to spawn count for enemy \"" + enemyName + "\". TurretHeadData is null.")); return; } enemyTurretHeadData.AddToSpawnCount(); Plugin.Instance.LogInfoExtended($"AddToEnemySpawnCount(); Enemy \"{enemyName}\" SpawnCount: {enemyTurretHeadData.SpawnCount}, MaxSpawnCount: {enemyTurretHeadData.GetSpawnDataForCurrentMoon().MaxSpawnCount}, SpawnChance: {enemyTurretHeadData.GetSpawnDataForCurrentMoon().SpawnChance}"); } internal static void AddToPlayerSpawnCount() { TurretHeadData playerTurretHeadData = PlayerTurretHeadData; playerTurretHeadData.AddToSpawnCount(); } public static TurretHeadData GetEnemyTurretHeadData(string enemyName, bool isSlayer) { foreach (TurretHeadData turretHeadData in TurretHeadDataList) { if (turretHeadData.EnemyName.Equals(enemyName, StringComparison.OrdinalIgnoreCase) && turretHeadData.IsSlayer == isSlayer) { return turretHeadData; } } return null; } public static void DespawnEnemyControllerOnServer(EnemyAI enemyScript) { if (!NetworkUtils.IsServer) { return; } string enemyName = enemyScript.enemyType.enemyName; if (EnemyTurretHeadControllerPairs.TryGetValue(enemyScript, out var value)) { NetworkObject val = default(NetworkObject); if (((Component)value).TryGetComponent<NetworkObject>(ref val)) { val.Despawn(true); Plugin.Instance.LogInfoExtended("Despawned enemy \"" + enemyName + "\" Turret-Head controller."); } else { Plugin.logger.LogError((object)("Error: Failed to despawn enemy \"" + enemyName + "\" Turret-Head controller. NetworkObject is null.")); } EnemyTurretHeadControllerPairs.Remove(enemyScript); } else { Plugin.logger.LogError((object)("Error: Failed to despawn enemy \"" + enemyName + "\" Turret-Head controller. Could not find value from key.")); } } public static void DespawnPlayerControllerOnServer(PlayerControllerB playerScript) { if (!NetworkUtils.IsServer) { return; } string playerUsername = playerScript.playerUsername; if (PlayerTurretHeadControllerPairs.TryGetValue(playerScript, out var value)) { NetworkObject val = default(NetworkObject); if (((Component)value).TryGetComponent<NetworkObject>(ref val)) { val.Despawn(true); Plugin.Instance.LogInfoExtended("Despawned player \"" + playerUsername + "\" Turret-Head controller."); } else { Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" Turret-Head controller. NetworkObject is null.")); } PlayerTurretHeadControllerPairs.Remove(playerScript); } else { Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" Turret-Head controller. Could not find value from key.")); } } public static void DespawnDeadBodyControllerOnServer(PlayerControllerB playerScript) { if (!NetworkUtils.IsServer) { return; } string playerUsername = playerScript.playerUsername; if (DeadBodyTurretHeadControllerPairs.TryGetValue(playerScript, out var value)) { NetworkObject val = default(NetworkObject); if (((Component)value).TryGetComponent<NetworkObject>(ref val)) { val.Despawn(true); Plugin.Instance.LogInfoExtended("Despawned player \"" + playerUsername + "\" ragdoll Turret-Head controller."); } else { Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" ragdoll Turret-Head controller. NetworkObject is null.")); } DeadBodyTurretHeadControllerPairs.Remove(playerScript); } else { Plugin.logger.LogError((object)("Error: Failed to despawn player \"" + playerUsername + "\" ragdoll Turret-Head controller. Could not find value from key.")); } } private static void DespawnAllControllersOnServer() { if (!NetworkUtils.IsServer) { return; } try { TurretHeadControllerBehaviour[] array = Object.FindObjectsByType<TurretHeadControllerBehaviour>((FindObjectsSortMode)0); NetworkObject val = default(NetworkObject); foreach (TurretHeadControllerBehaviour turretHeadControllerBehaviour in array) { if (!((Component)turretHeadControllerBehaviour).TryGetComponent<NetworkObject>(ref val)) { Plugin.logger.LogError((object)"Error: Failed to despawn TurretHeadBehaviour. NetworkObject is null."); } else { val.Despawn(true); } } Plugin.Instance.LogInfoExtended("Finished despawning all TurretHeadBehaviour(s)."); } catch (Exception arg) { Plugin.logger.LogError((object)$"Error: Failed to despawn all TurretHeadBehaviour(s).\n\n{arg}"); } } public static bool IsEnemyTurretHead(EnemyAI enemyScript) { return EnemyTurretHeadControllerPairs.ContainsKey(enemyScript); } public static bool IsPlayerTurretHead(PlayerControllerB playerScript) { return PlayerTurretHeadControllerPairs.ContainsKey(playerScript); } public static bool IsDeadBodyTurretHead(PlayerControllerB playerScript) { return DeadBodyTurretHeadControllerPairs.ContainsKey(playerScript); } } public static class Utils { [CompilerGenerated] private sealed class <WaitUntil>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int iterationsPerSecond; public Func<bool> predicate; public float maxDuration; private float <timer>5__2; private float <timePerIteration>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitUntil>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <timer>5__2 = 0f; <timePerIteration>5__3 = 1f / (float)iterationsPerSecond; break; case 1: <>1__state = -1; <timer>5__2 += Time.deltaTime; break; } if (<timer>5__2 < maxDuration && !predicate()) { <>2__current = (object)new WaitForSeconds(<timePerIteration>5__3); <>1__state = 1; return true; } 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 bool RandomPercent(float percent) { if (percent <= 0f) { return false; } if (percent >= 100f) { return true; } return Random.value * 100f <= percent; } public static void DisableColliders(GameObject gameObject, bool keepScanNodeEnabled = false) { Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>(); Collider[] array = componentsInChildren; foreach (Collider val in array) { if (!keepScanNodeEnabled || !(((Object)((Component)val).gameObject).name == "ScanNode")) { val.enabled = false; } } } public static void DisableRenderers(GameObject gameObject) { MeshRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val in componentsInChildren) { ((Renderer)val).enabled = false; } SkinnedMeshRenderer[] componentsInChildren2 = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { ((Renderer)val2).enabled = false; } } [IteratorStateMachine(typeof(<WaitUntil>d__3))] public static IEnumerator WaitUntil(Func<bool> predicate, float maxDuration = 5f, int iterationsPerSecond = 10) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitUntil>d__3(0) { predicate = predicate, maxDuration = maxDuration, iterationsPerSecond = iterationsPerSecond }; } public static bool IsValidEnemy(EnemyAI enemyScript) { if (IsSpring(enemyScript)) { return true; } if (IsManticoil(enemyScript)) { return true; } if (IsMasked(enemyScript)) { return true; } return false; } public static bool IsSpring(EnemyAI enemyScript) { return enemyScript.enemyType.enemyName == "Spring"; } public static bool IsManticoil(EnemyAI enemyScript) { return enemyScript.enemyType.enemyName == "Manticoil"; } public static bool IsMasked(EnemyAI enemyScript) { return enemyScript.enemyType.enemyName == "Masked"; } public static bool IsTurretHead(EnemyAI enemyScript) { return (Object)(object)((Component)enemyScript).GetComponentInChildren<TurretHeadControllerBehaviour>() != (Object)null; } public static bool IsTurretHead(PlayerControllerB playerScript) { return (Object)(object)((Component)playerScript).GetComponentInChildren<TurretHeadControllerBehaviour>() != (Object)null; } public static bool IsTurretHead(DeadBodyInfo deadBodyScript) { return (Object)(object)((Component)deadBodyScript).GetComponentInChildren<TurretHeadControllerBehaviour>() != (Object)null; } public static bool IsCurrentMoonToilation() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return false; } string planetName = StartOfRound.Instance.currentLevel.PlanetName; if (planetName.Equals("69 Toilation", StringComparison.OrdinalIgnoreCase)) { return true; } if (planetName.Contains("Toilation", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.github.zehsteam.ToilHead"; public const string PLUGIN_NAME = "ToilHead"; public const string PLUGIN_VERSION = "1.9.1"; } } namespace com.github.zehsteam.ToilHead.Patches { [HarmonyPatch(typeof(EnemyAI))] internal static class EnemyAIPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch(ref EnemyAI __instance) { if (Utils.IsValidEnemy(__instance) && !TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: true)) { TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: false); } } [HarmonyPatch("HitEnemyServerRpc")] [HarmonyPostfix] private static void HitEnemyServerRpcPatch(ref EnemyAI __instance, int playerWhoHit) { if (!__instance.isEnemyDead && TurretHeadManager.EnemyTurretHeadControllerPairs.TryGetValue(__instance, out var value) && value.TurretBehaviour.turretActive) { value.TurretBehaviour.EnterBerserkModeClientRpc(); } } [HarmonyPatch("KillEnemy")] [HarmonyPrefix] private static void KillEnemyPatch(ref EnemyAI __instance, bool destroy) { if (NetworkUtils.IsServer && destroy && TurretHeadManager.IsEnemyTurretHead(__instance)) { TurretHeadManager.DespawnEnemyControllerOnServer(__instance); } } } [HarmonyPatch(typeof(GameNetworkManager))] internal static class GameNetworkManagerPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch() { AddNetworkPrefabs(); } private static void AddNetworkPrefabs() { AddNetworkPrefab(Content.NetworkHandlerPrefab); AddNetworkPrefab(Content.ToilHeadControllerPrefab); AddNetworkPrefab(Content.ToilSlayerControllerPrefab); AddNetworkPrefab(Content.MantiToilControllerPrefab); AddNetworkPrefab(Content.MantiSlayerControllerPrefab); AddNetworkPrefab(Content.ToilPlayerControllerPrefab); AddNetworkPrefab(Content.SlayerPlayerControllerPrefab); AddNetworkPrefab(Content.ToiledDeadBodyControllerPrefab); AddNetworkPrefab(Content.SlayedDeadBodyControllerPrefab); AddNetworkPrefab(Content.ToilMaskedControllerPrefab); AddNetworkPrefab(Content.SlayerMaskedControllerPrefab); } private static void AddNetworkPrefab(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { Plugin.logger.LogError((object)"Error: Failed to register network prefab. Prefab is null."); return; } NetworkManager.Singleton.AddNetworkPrefab(prefab); Plugin.logger.LogInfo((object)("Registered \"" + ((Object)prefab).name + "\" network prefab.")); } } [HarmonyPatch(typeof(MaskedPlayerEnemy))] internal static class MaskedPlayerEnemyPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch(ref EnemyAI __instance) { if (!TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: true)) { TurretHeadManager.TrySetEnemyTurretHeadOnServer(__instance, isSlayer: false); } } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { [HarmonyPatch("KillPlayerServerRpc")] [HarmonyPrefix] private static void KillPlayerServerRpcPatch(ref PlayerControllerB __instance) { if (TurretHeadManager.IsPlayerTurretHead(__instance)) { TurretHeadManager.DespawnPlayerControllerOnServer(__instance); } } [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroyPatch(ref PlayerControllerB __instance) { if (NetworkUtils.IsServer && TurretHeadManager.IsPlayerTurretHead(__instance)) { TurretHeadManager.DespawnPlayerControllerOnServer(__instance); } } } [HarmonyPatch(typeof(RagdollGrabbableObject))] internal static class RagdollGrabbableObjectPatch { [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroyPatch(ref RagdollGrabbableObject __instance) { if (NetworkUtils.IsServer && !((Object)(object)__instance.ragdoll == (Object)null) && !((Object)(object)__instance.ragdoll.playerScript == (Object)null)) { PlayerControllerB playerScript = __instance.ragdoll.playerScript; if (TurretHeadManager.IsDeadBodyTurretHead(playerScript)) { TurretHeadManager.DespawnDeadBodyControllerOnServer(playerScript); } } } } [HarmonyPatch(typeof(RoundManager))] internal static class RoundManagerPatch { [HarmonyPatch("LoadNewLevel")] [HarmonyPostfix] private static void LoadNewLevelPatch() { Plugin.Instance.OnNewLevelLoaded(); } [HarmonyPatch("GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void GenerateNewLevelClientRpcPatch() { if (!NetworkUtils.IsServer) { Plugin.Instance.OnNewLevelLoaded(); } } [HarmonyPatch("FinishGeneratingNewLevelClientRpc")] [HarmonyPostfix] private static void FinishGeneratingNewLevelClientRpcPatch() { Plugin.Instance.OnNewLevelFinishedLoading(); } } [HarmonyPatch(typeof(SpringManAI))] internal static class SpringManAIPatch { [HarmonyPatch("OnCollideWithPlayer")] [HarmonyPostfix] private static void OnCollideWithPlayerPatch(ref SpringManAI __instance, ref Collider other) { TurretHeadControllerBehaviour componentInChildren = ((Component)__instance).GetComponentInChildren<TurretHeadControllerBehaviour>(); if (!((Object)(object)componentInChildren == (Object)null)) { PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if (!((Object)(object)component == (Object)null) && PlayerUtils.IsLocalPlayer(component) && component.AllowPlayerDeath()) { bool isMinigun = componentInChildren.TurretBehaviour.IsMinigun; Plugin.Instance.LogInfoExtended($"SpringManAI OnCollideWithPlayer \"{component.playerUsername}\" isSlayer? {isMinigun}"); TurretHeadManager.SetDeadBodyTurretHead(component, isMinigun); } } } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePatch() { SpawnNetworkHandler(); } private static void SpawnNetworkHandler() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (NetworkUtils.IsServer) { GameObject val = Object.Instantiate<GameObject>(Content.NetworkHandlerPrefab, Vector3.zero, Quaternion.identity); val.GetComponent<NetworkObject>().Spawn(false); } } [HarmonyPatch("OnClientConnect")] [HarmonyPrefix] private static void OnClientConnectPatch(ref ulong clientId) { SendConfigToNewConnectedPlayer(clientId); } private static void SendConfigToNewConnectedPlayer(ulong clientId) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (NetworkUtils.IsServer) { ClientRpcParams val = default(ClientRpcParams); val.Send = new ClientRpcSendParams { TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(clientId) }; ClientRpcParams clientRpcParams = val; Plugin.logger.LogInfo((object)$"Sending config to client: {clientId}"); PluginNetworkBehaviour.Instance.SendConf