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 Hung to Dry v1.0.0
HungToDry.dll
Decompiled 3 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 SpiderCocoon { [BepInPlugin("Militus.HungToDry", "Hung to Dry", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<float> HoldSeconds; internal static ConfigEntry<float> HangSeconds; internal static ConfigEntry<float> ImmunitySeconds; internal static ConfigEntry<Key> CutDownKey; internal static ConfigEntry<float> StuckSeconds; internal static ConfigEntry<float> CutDownSeconds; internal static ConfigEntry<bool> DropHeldItems; internal static ConfigEntry<float> LookSensitivity; internal static ConfigEntry<bool> EnableDebugSpawn; internal static ConfigEntry<Key> DebugSpawnKey; private void Awake() { //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; HoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "VictimHoldSeconds", 60f, "Safety net: if the spider has NOT hung the victim up after this many seconds, they are released."); HangSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SecondsHangingBeforeDeath", 45f, "How many seconds a victim stays hung up before they die."); ImmunitySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ImmunitySeconds", 10f, "Seconds after a release during which the spider cannot cocoon the player again."); DropHeldItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DropHeldItems", true, "Victims drop the items they are holding when they are caught."); CutDownKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Rescue", "CutDownKey", (Key)19, "Hold this key near a hung cocoon to cut the victim down."); CutDownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Rescue", "CutDownSeconds", 4f, "How many seconds the key must be held to cut a victim down."); StuckSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "StuckSeconds", 12f, "If a spider stands still this many seconds while carrying a victim, it hangs them where it stands."); LookSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "LookSensitivity", 0.12f, "How fast the mouse turns the camera while you are wrapped up. Mouse wheel zooms in and out."); EnableDebugSpawn = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "EnableDebugSpawnKey", false, "Testing only: lets the HOST press F8 to spawn a bunker spider in front of them (and F7 to log nearby labels). Leave this off for normal play."); DebugSpawnKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Testing", "DebugSpawnKey", (Key)101, "The key that spawns a bunker spider (host only, needs EnableDebugSpawnKey)."); CocoonRunner.Ensure(); Harmony val = new Harmony("Militus.HungToDry"); val.PatchAll(); try { MethodBase methodBase = AccessTools.Method(typeof(EnemyAI), "PlayerIsTargetable", (Type[])null, (Type[])null); if (methodBase != null) { val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(SpiderTargetPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.LogWarning((object)"Could not find EnemyAI.PlayerIsTargetable; spiders may re-target frozen players."); } } catch (Exception ex) { Log.LogWarning((object)("Could not patch PlayerIsTargetable: " + ex.Message)); } Log.LogInfo((object)"Hung to Dry 1.0.0 loaded (spider camera, death timer, cut-down rescue, anti-stall)."); } } internal class CocoonRunner : MonoBehaviour { private static CocoonRunner instance; public static void Ensure() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)instance != (Object)null)) { GameObject val = new GameObject("SpiderCocoonRunner"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); instance = val.AddComponent<CocoonRunner>(); } } public static void Run(IEnumerator routine) { Ensure(); ((MonoBehaviour)instance).StartCoroutine(routine); } private void Update() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current != null && ((ButtonControl)current.f9Key).wasPressedThisFrame) { Cocoon.EmergencyRelease(); } if (Plugin.EnableDebugSpawn.Value && current != null) { KeyControl val = current[Plugin.DebugSpawnKey.Value]; if (val != null && ((ButtonControl)val).wasPressedThisFrame) { DebugSpawn.SpawnSpiderInFrontOfHost(); } if (((ButtonControl)current.f7Key).wasPressedThisFrame) { DebugSpawn.DumpLabelsNearby(); } } Cocoon.RemoveDeadVictims(); CocoonNet.EnsureRegistered(); Cocoon.WatchSpiders(); } private void LateUpdate() { Cocoon.UpdateCameras(); Cocoon.UpdateRescue(); } } internal static class DebugSpawn { private static string PathOf(Transform t) { string text = ((Object)t).name; int num = 0; while ((Object)(object)t.parent != (Object)null && num++ < 8) { t = t.parent; text = ((Object)t).name + "/" + text; } return text; } internal static void DumpLabelsNearby() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Invalid comparison between Unknown and I4 //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) try { PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null) { return; } Vector3 position = ((Component)val).transform.position; Plugin.Log.LogInfo((object)"=== Label dump (F7) ==="); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val2 in allPlayerScripts) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && val2.isPlayerControlled) { Plugin.Log.LogInfo((object)("Player " + val2.playerClientId + " (" + val2.playerUsername + ") cocooned=" + Cocoon.IsCocooned(val2) + " canvasActive=" + ((Object)(object)val2.usernameCanvas != (Object)null && ((Component)val2.usernameCanvas).gameObject.activeSelf) + " alpha=" + (((Object)(object)val2.usernameAlpha != (Object)null) ? val2.usernameAlpha.alpha : (-1f)) + " dist=" + Vector3.Distance(position, ((Component)val2).transform.position))); } } Canvas[] array = Object.FindObjectsOfType<Canvas>(); foreach (Canvas val3 in array) { if (!((Object)(object)val3 == (Object)null) && ((Component)val3).gameObject.activeInHierarchy && (int)val3.renderMode == 2) { float num = Vector3.Distance(position, ((Component)val3).transform.position); if (!(num > 20f)) { Plugin.Log.LogInfo((object)("WorldCanvas " + PathOf(((Component)val3).transform) + " dist=" + num)); } } } ScanNodeProperties[] array2 = Object.FindObjectsOfType<ScanNodeProperties>(); foreach (ScanNodeProperties val4 in array2) { if (!((Object)(object)val4 == (Object)null) && ((Component)val4).gameObject.activeInHierarchy) { float num2 = Vector3.Distance(position, ((Component)val4).transform.position); if (!(num2 > 20f)) { Plugin.Log.LogInfo((object)("ScanNode '" + val4.headerText + "' / '" + val4.subText + "' " + PathOf(((Component)val4).transform) + " dist=" + num2)); } } } Plugin.Log.LogInfo((object)"=== End label dump ==="); } catch (Exception ex) { Plugin.Log.LogError((object)("Label dump failed: " + ex)); } } internal unsafe static void SpawnSpiderInFrontOfHost() { //IL_0100: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { Plugin.Log.LogWarning((object)"Spawn key: only the host can spawn a spider."); return; } PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"Spawn key: no local player yet."); return; } EnemyType val2 = null; EnemyType[] array = Resources.FindObjectsOfTypeAll<EnemyType>(); foreach (EnemyType val3 in array) { if ((Object)(object)val3 != (Object)null && (Object)(object)val3.enemyPrefab != (Object)null && (Object)(object)val3.enemyPrefab.GetComponentInChildren<SandSpiderAI>() != (Object)null) { val2 = val3; break; } } if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"Spawn key: could not find the bunker spider type."); return; } Vector3 val4 = ((Component)val).transform.position + ((Component)val).transform.forward * 7f; NavMeshHit val5 = default(NavMeshHit); if (NavMesh.SamplePosition(val4, ref val5, 8f, -1)) { val4 = ((NavMeshHit)(ref val5)).position; } GameObject val6 = Object.Instantiate<GameObject>(val2.enemyPrefab, val4, Quaternion.identity); NetworkObject componentInChildren = val6.GetComponentInChildren<NetworkObject>(); if ((Object)(object)componentInChildren == (Object)null) { Object.Destroy((Object)(object)val6); Plugin.Log.LogWarning((object)"Spawn key: spider prefab has no network object."); return; } componentInChildren.Spawn(true); EnemyAI componentInChildren2 = val6.GetComponentInChildren<EnemyAI>(); if ((Object)(object)componentInChildren2 != (Object)null && (Object)(object)RoundManager.Instance != (Object)null && RoundManager.Instance.SpawnedEnemies != null) { RoundManager.Instance.SpawnedEnemies.Add(componentInChildren2); } ManualLogSource log = Plugin.Log; Vector3 val7 = val4; log.LogInfo((object)("Spawn key: bunker spider spawned at " + ((object)(*(Vector3*)(&val7))/*cast due to .constrained prefix*/).ToString() + ".")); } catch (Exception ex) { Plugin.Log.LogError((object)("Spawn key failed: " + ex)); } } } internal class CocoonState { public PlayerControllerB Player; public SandSpiderAI Spider; public List<Renderer> Renderers = new List<Renderer>(); public List<bool> WereEnabled = new List<bool>(); public List<Collider> Colliders = new List<Collider>(); public List<bool> ColliderWasEnabled = new List<bool>(); public bool Hung; public float BeganAt; public bool DiagLogged; public float LostSince = -1f; public Vector3 LastSpiderPos; public float StillSince = -1f; public bool CameraActive; public bool CamInitialized; public Vector3 CamDir = Vector3.forward; public float OrbitYaw; public float OrbitPitch; public float ZoomMul = 1f; public Vector3 SavedLocalPos; public Quaternion SavedLocalRot; } internal static class Cocoon { private const float CamDistance = 3.5f; private const float CamHeight = 1.2f; private static readonly Dictionary<int, CocoonState> Active = new Dictionary<int, CocoonState>(); private static readonly Dictionary<int, float> ImmuneUntil = new Dictionary<int, float>(); private static readonly MethodInfo GrabBodyMethod = AccessTools.Method(typeof(SandSpiderAI), "GrabBody", (Type[])null, (Type[])null); private static readonly MethodInfo CancelSpoolingMethod = AccessTools.Method(typeof(SandSpiderAI), "CancelSpoolingBody", (Type[])null, (Type[])null); private static readonly FieldInfo SpooledField = AccessTools.Field(typeof(SandSpiderAI), "spooledPlayerBody"); private static readonly FieldInfo HeldBodyField = AccessTools.Field(typeof(SandSpiderAI), "currentlyHeldBody"); private static readonly FieldInfo SpoolingField = AccessTools.Field(typeof(SandSpiderAI), "spoolingPlayerBody"); private static readonly MethodInfo HangBodyMethod = AccessTools.Method(typeof(SandSpiderAI), "HangBodyFromCeiling", (Type[])null, (Type[])null); private static readonly FieldInfo StunField = AccessTools.Field(typeof(EnemyAI), "stunNormalizedTimer"); private static readonly FieldInfo CoroutineField = AccessTools.Field(typeof(SandSpiderAI), "turnBodyIntoWebCoroutine"); private static readonly MethodInfo WrapMethod = AccessTools.Method(typeof(SandSpiderAI), "turnBodyIntoWeb", (Type[])null, (Type[])null); private const float RescueRange = 5f; private static int cutTarget = -1; private static float cutProgress; private static float lastRequestTime = -10f; private static bool promptShown; public static bool IsCocooned(PlayerControllerB player) { return (Object)(object)player != (Object)null && Active.ContainsKey((int)player.playerClientId); } public static bool IsImmune(PlayerControllerB player) { float value; return (Object)(object)player != (Object)null && ImmuneUntil.TryGetValue((int)player.playerClientId, out value) && Time.time < value; } private static bool IsLocal(PlayerControllerB p) { return (Object)(object)p != (Object)null && (Object)(object)p == (Object)(object)GameNetworkManager.Instance.localPlayerController; } private static void MakeSpiderGrab(SandSpiderAI spider, PlayerControllerB victim) { if ((Object)(object)spider == (Object)null || ((EnemyAI)spider).isEnemyDead || !((NetworkBehaviour)spider).IsOwner) { return; } DeadBodyInfo deadBody = victim.deadBody; if (!((Object)(object)deadBody == (Object)null)) { if (!(bool)SpoolingField.GetValue(spider)) { CoroutineField.SetValue(spider, null); } SpooledField.SetValue(spider, false); GrabBodyMethod.Invoke(spider, new object[1] { deadBody }); spider.GrabBodyServerRpc((int)victim.playerClientId); ((EnemyAI)spider).targetPlayer = null; ((EnemyAI)spider).SwitchToBehaviourState(1); Plugin.Log.LogInfo((object)("Spider grabbed player " + victim.playerClientId + "'s stand-in body.")); } } public static void Begin(PlayerControllerB victim, SandSpiderAI spider) { //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)victim == (Object)null || victim.isPlayerDead) { return; } int num = (int)victim.playerClientId; if (Active.ContainsKey(num)) { return; } CocoonState cocoonState = new CocoonState { Player = victim, Spider = spider, BeganAt = Time.time }; Active[num] = cocoonState; if (ImmuneUntil.TryGetValue(num, out var value)) { Plugin.Log.LogInfo((object)("Player " + num + " caught again; their immunity ended " + (Time.time - value).ToString("F1") + "s ago (negative = they were still immune).")); } bool flag = IsLocal(victim); try { CocoonRunner.Run(FailsafeRelease(num, cocoonState, Plugin.HoldSeconds.Value)); Renderer[] componentsInChildren = ((Component)victim).gameObject.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && (val is SkinnedMeshRenderer || val is MeshRenderer) && !((Object)(object)((Component)val).GetComponentInParent<GrabbableObject>() != (Object)null)) { cocoonState.Renderers.Add(val); cocoonState.WereEnabled.Add(val.enabled); val.enabled = false; } } if (!flag) { AddCollider(cocoonState, (Collider)(object)victim.thisController); AddCollider(cocoonState, victim.playerCollider); Collider[] componentsInChildren2 = ((Component)victim).gameObject.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).GetComponentInParent<GrabbableObject>() != (Object)null)) { AddCollider(cocoonState, val2); } } DisableColliders(cocoonState); Plugin.Log.LogInfo((object)("Player " + num + ": switched off " + cocoonState.Colliders.Count + " collider(s) so nobody bumps into the hidden body.")); } if (flag) { victim.disableMoveInput = true; victim.disableLookInput = true; if (Plugin.DropHeldItems.Value) { victim.DropAllHeldItemsAndSync(((Component)victim).transform.position, victim.localItemHolder.position, victim.localItemHolder.eulerAngles, victim.playerEye.position, victim.playerEye.eulerAngles); } } victim.SpawnDeadBody(num, Vector3.zero, 6, victim, 0, (Transform)null, (Transform)null, default(Vector3)); MakeSpiderGrab(spider, victim); if (flag) { StartCamera(cocoonState); } Plugin.Log.LogInfo((object)("Player " + num + " cocooned (this is my own player: " + flag + ").")); } catch (Exception ex) { Plugin.Log.LogError((object)("Cocoon.Begin failed, undoing: " + ex)); End(num); } } public static void OnBodyHung(DeadBodyInfo body, SandSpiderAI spider = null) { if ((Object)(object)body == (Object)null && (Object)(object)spider == (Object)null) { return; } foreach (KeyValuePair<int, CocoonState> item in Active) { CocoonState value = item.Value; if (value.Hung || (Object)(object)value.Player == (Object)null || !(((Object)(object)body != (Object)null) ? ((Object)(object)value.Player.deadBody == (Object)(object)body) : ((Object)(object)value.Spider == (Object)(object)spider))) { continue; } value.Hung = true; CocoonRunner.Run(DeathAfter(item.Key, value, Plugin.HangSeconds.Value)); Plugin.Log.LogInfo((object)("Player " + item.Key + " hung up. Death in " + Plugin.HangSeconds.Value + "s.")); break; } } private static bool SpiderHoldsBody(SandSpiderAI spider) { return (Object)(object)spider != (Object)null && HeldBodyField.GetValue(spider) != null; } private static IEnumerator WaitForHeldBody(SandSpiderAI spider, Action<bool> ready) { float waited = 0f; while ((Object)(object)spider != (Object)null && !SpiderHoldsBody(spider) && waited < 10f) { waited += Time.deltaTime; yield return null; } ready((Object)(object)spider != (Object)null && !((EnemyAI)spider).isEnemyDead && SpiderHoldsBody(spider)); } internal static IEnumerator WrapWhenReady(SandSpiderAI spider) { bool ok = false; yield return CocoonRunnerWait(spider, delegate(bool r) { ok = r; }); if (!ok || CoroutineField.GetValue(spider) != null) { yield break; } try { CoroutineField.SetValue(spider, ((MonoBehaviour)spider).StartCoroutine((IEnumerator)WrapMethod.Invoke(spider, null))); } catch (Exception ex) { Plugin.Log.LogError((object)("Late wrap failed: " + ex)); } } internal static IEnumerator HangWhenReady(SandSpiderAI spider) { bool ok = false; yield return CocoonRunnerWait(spider, delegate(bool r) { ok = r; }); if (!ok) { OnBodyHung(null, spider); yield break; } yield return (object)new WaitForSeconds(0.3f); float waited = 0f; while ((Object)(object)spider != (Object)null && CoroutineField.GetValue(spider) != null && waited < 8f) { waited += Time.deltaTime; yield return null; } if ((Object)(object)spider == (Object)null || ((EnemyAI)spider).isEnemyDead || !SpiderHoldsBody(spider)) { yield break; } try { HangBodyMethod.Invoke(spider, null); } catch (Exception ex) { Plugin.Log.LogError((object)("Late hang failed: " + ex)); } } private static IEnumerator CocoonRunnerWait(SandSpiderAI spider, Action<bool> ready) { return WaitForHeldBody(spider, ready); } private static IEnumerator FailsafeRelease(int id, CocoonState owner, float seconds) { yield return (object)new WaitForSeconds(seconds); if (Active.TryGetValue(id, out var s) && s == owner && !s.Hung) { Plugin.Log.LogInfo((object)("Player " + id + " was never hung up: safety release.")); End(id); } } private static IEnumerator DeathAfter(int id, CocoonState owner, float seconds) { yield return (object)new WaitForSeconds(seconds); if (!Active.TryGetValue(id, out var current) || current != owner) { yield break; } try { Kill(id); } catch (Exception ex) { Plugin.Log.LogError((object)("Kill failed: " + ex)); } } public static void Kill(int id) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (Active.TryGetValue(id, out var value)) { PlayerControllerB player = value.Player; if (IsLocal(player)) { Active.Remove(id); StopCamera(value, backToPlayer: false); player.disableMoveInput = false; player.disableLookInput = false; Plugin.Log.LogInfo((object)("Player " + id + " dies in the cocoon.")); player.KillPlayer(Vector3.zero, false, (CauseOfDeath)6, 0, default(Vector3), false); } } } public static void EndAll() { foreach (int item in new List<int>(Active.Keys)) { End(item); } } public static void EmergencyRelease() { GameNetworkManager instance = GameNetworkManager.Instance; PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null); if (!((Object)(object)val == (Object)null)) { int num = (int)val.playerClientId; if (Active.ContainsKey(num)) { Plugin.Log.LogInfo((object)("Emergency release (F9) for player " + num + ".")); End(num); CocoonNet.RequestRelease(num); } } } private static void AddCollider(CocoonState state, Collider c) { if (!((Object)(object)c == (Object)null) && !state.Colliders.Contains(c)) { state.Colliders.Add(c); state.ColliderWasEnabled.Add(c.enabled); } } private static void DisableColliders(CocoonState state) { for (int i = 0; i < state.Colliders.Count; i++) { if ((Object)(object)state.Colliders[i] != (Object)null && state.Colliders[i].enabled) { state.Colliders[i].enabled = false; } } } private static void RestoreColliders(CocoonState state) { for (int i = 0; i < state.Colliders.Count; i++) { if ((Object)(object)state.Colliders[i] != (Object)null) { state.Colliders[i].enabled = state.ColliderWasEnabled[i]; } } } public static void End(int id, bool teleportToBody = false) { if (!Active.TryGetValue(id, out var value)) { return; } Active.Remove(id); PlayerControllerB player = value.Player; if ((Object)(object)player != (Object)null && !player.isPlayerDead) { RestoreColliders(value); } if ((Object)(object)player == (Object)null || player.isPlayerDead) { StopCamera(value, backToPlayer: false); return; } ImmuneUntil[id] = Time.time + Plugin.ImmunitySeconds.Value; StopCamera(value, backToPlayer: true); for (int i = 0; i < value.Renderers.Count; i++) { if ((Object)(object)value.Renderers[i] != (Object)null) { value.Renderers[i].enabled = value.WereEnabled[i]; } } if (IsLocal(player)) { player.disableMoveInput = false; player.disableLookInput = false; } if ((Object)(object)player.deadBody != (Object)null) { SandSpiderAI spider = value.Spider; if ((Object)(object)spider != (Object)null && !((EnemyAI)spider).isEnemyDead && HeldBodyField.GetValue(spider) == player.deadBody) { CancelSpoolingMethod.Invoke(spider, null); CoroutineField.SetValue(spider, null); } if (teleportToBody && value.Hung && IsLocal(player)) { MoveVictimUnderBody(player); } Transform attachedTo = player.deadBody.attachedTo; Object.Destroy((Object)(object)((Component)player.deadBody).gameObject); player.deadBody = null; if (value.Hung && (Object)(object)attachedTo != (Object)null) { DestroyRope(attachedTo); } } Plugin.Log.LogInfo((object)("Player " + id + " released (this is my own player: " + IsLocal(player) + ").")); } public static void WatchSpiders() { //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03b8: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) if (Active.Count == 0) { return; } foreach (CocoonState item in new List<CocoonState>(Active.Values)) { SandSpiderAI spider = item.Spider; if (!item.DiagLogged && !item.Hung && (Object)(object)spider != (Object)null && (Object)(object)item.Player != (Object)null && Time.time - item.BeganAt > 25f) { item.DiagLogged = true; try { Plugin.Log.LogWarning((object)("Spider diagnostic: player " + item.Player.playerClientId + " wrapped 25s but not hung. state=" + ((EnemyAI)spider).currentBehaviourStateIndex + " owner=" + ((NetworkBehaviour)spider).IsOwner + " spooling=" + SpoolingField.GetValue(spider)?.ToString() + " spooled=" + SpooledField.GetValue(spider)?.ToString() + " wrapRoutineSet=" + (CoroutineField.GetValue(spider) != null) + " holdingTheirBody=" + (HeldBodyField.GetValue(spider) == item.Player.deadBody) + " stunTimer=" + ((StunField != null) ? StunField.GetValue(spider) : null))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Spider diagnostic failed: " + ex.Message)); } } if (item.Hung || (Object)(object)spider == (Object)null || ((EnemyAI)spider).isEnemyDead || !((NetworkBehaviour)spider).IsOwner || (Object)(object)item.Player == (Object)null) { continue; } DeadBodyInfo deadBody = item.Player.deadBody; if ((Object)(object)deadBody == (Object)null || HeldBodyField.GetValue(spider) != deadBody) { item.StillSince = -1f; if ((Object)(object)deadBody != (Object)null && Time.time - item.BeganAt > 6f) { if (item.LostSince < 0f) { item.LostSince = Time.time; } else if (Time.time - item.LostSince > 4f) { Plugin.Log.LogWarning((object)("Spider dropped player " + item.Player.playerClientId + " without hanging them: releasing them.")); item.LostSince = -1f; CocoonNet.RequestRelease((int)item.Player.playerClientId); } } continue; } item.LostSince = -1f; bool flag = (bool)SpoolingField.GetValue(spider); if (StunField != null && (float)StunField.GetValue(spider) > 0f) { flag = true; } Vector3 val = (((Object)(object)spider.meshContainer != (Object)null) ? spider.meshContainer.position : ((Component)spider).transform.position); if (item.StillSince < 0f || flag || Vector3.Distance(val, item.LastSpiderPos) > 0.5f) { item.LastSpiderPos = val; item.StillSince = Time.time; } else { if (Time.time - item.StillSince < Plugin.StuckSeconds.Value) { continue; } Plugin.Log.LogWarning((object)("Spider stuck while carrying player " + item.Player.playerClientId + ": hanging them where it stands.")); item.StillSince = -1f; try { HangBodyMethod.Invoke(spider, null); spider.SpiderHangBodyServerRpc(); ((EnemyAI)spider).targetPlayer = null; if (((EnemyAI)spider).currentBehaviourStateIndex == 2) { ((EnemyAI)spider).SwitchToBehaviourState(0); } } catch (Exception ex2) { Plugin.Log.LogError((object)("Unsticking the spider failed: " + ex2)); } } } } public static void ApplyRelease(int id) { if (Active.TryGetValue(id, out var _)) { Plugin.Log.LogInfo((object)("Player " + id + " was cut down.")); End(id, teleportToBody: true); } } private static void MoveVictimUnderBody(PlayerControllerB p) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = ((Component)p.deadBody.bodyParts[6]).transform.position; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 25f, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1)) { val = ((RaycastHit)(ref val2)).point + Vector3.up * 0.3f; } p.TeleportPlayer(val, false, 0f, false, true); } catch (Exception ex) { Plugin.Log.LogError((object)("Could not move the freed player to the cocoon: " + ex)); } } private static void DestroyRope(Transform hangPoint) { try { SetLineRendererPoints componentInParent = ((Component)hangPoint).GetComponentInParent<SetLineRendererPoints>(); if ((Object)(object)componentInParent != (Object)null) { Object.Destroy((Object)(object)((Component)componentInParent).gameObject); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not remove the rope: " + ex.Message)); } } public static void UpdateRescue() { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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) GameNetworkManager instance = GameNetworkManager.Instance; PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null); if ((Object)(object)val == (Object)null) { return; } int num = -1; if (val.isPlayerControlled && !val.isPlayerDead && !IsCocooned(val) && !val.isTypingChat && !val.inTerminalMenu && !val.inSpecialMenu && ((Object)(object)val.quickMenuManager == (Object)null || !val.quickMenuManager.isMenuOpen) && Time.time - lastRequestTime > 2f && Active.Count > 0) { float num2 = 5f; Vector3 position = ((Component)val.gameplayCamera).transform.position; foreach (KeyValuePair<int, CocoonState> item in Active) { CocoonState value = item.Value; if (!value.Hung || (Object)(object)value.Player == (Object)null || (Object)(object)value.Player == (Object)(object)val) { continue; } DeadBodyInfo deadBody = value.Player.deadBody; if (!((Object)(object)deadBody == (Object)null) && deadBody.bodyParts != null && deadBody.bodyParts.Length > 6) { float num3 = Vector3.Distance(position, ((Component)deadBody.bodyParts[6]).transform.position); if (num3 < num2) { num2 = num3; num = item.Key; } } } } if (num < 0) { cutTarget = -1; cutProgress = 0f; if (promptShown) { promptShown = false; ((TMP_Text)val.cursorTip).text = ""; } return; } if (num != cutTarget) { cutTarget = num; cutProgress = 0f; } Keyboard current2 = Keyboard.current; bool flag = current2 != null && ((ButtonControl)current2[Plugin.CutDownKey.Value]).isPressed; cutProgress = (flag ? (cutProgress + Time.deltaTime) : 0f); float num4 = Mathf.Max(0.5f, Plugin.CutDownSeconds.Value); int num5 = Mathf.Min(100, Mathf.RoundToInt(cutProgress / num4 * 100f)); ((TMP_Text)val.cursorTip).text = (flag ? ("Cutting them down... " + num5 + "%") : ("[Hold " + ((object)Plugin.CutDownKey.Value/*cast due to .constrained prefix*/).ToString() + "] Cut them down")); promptShown = true; if (cutProgress >= num4) { cutProgress = 0f; cutTarget = -1; lastRequestTime = Time.time; Plugin.Log.LogInfo((object)("Cutting down player " + num)); CocoonNet.RequestRelease(num); } } public static void RemoveDeadVictims() { if (Active.Count == 0) { return; } foreach (int item in new List<int>(Active.Keys)) { CocoonState cocoonState = Active[item]; if ((Object)(object)cocoonState.Player == (Object)null || cocoonState.Player.isPlayerDead) { StopCamera(cocoonState, backToPlayer: false); Active.Remove(item); } } } private static void StartCamera(CocoonState s) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.spectateCamera == (Object)null)) { Camera spectateCamera = instance.spectateCamera; s.SavedLocalPos = ((Component)spectateCamera).transform.localPosition; s.SavedLocalRot = ((Component)spectateCamera).transform.localRotation; instance.SwitchCamera(spectateCamera); s.Player.ChangeAudioListenerToObject(((Component)spectateCamera).gameObject); s.CameraActive = true; } } private static void StopCamera(CocoonState s, bool backToPlayer) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!s.CameraActive) { return; } s.CameraActive = false; StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null)) { if ((Object)(object)instance.spectateCamera != (Object)null) { ((Component)instance.spectateCamera).transform.localPosition = s.SavedLocalPos; ((Component)instance.spectateCamera).transform.localRotation = s.SavedLocalRot; } if (backToPlayer && (Object)(object)s.Player != (Object)null && (Object)(object)s.Player.gameplayCamera != (Object)null) { instance.SwitchCamera(s.Player.gameplayCamera); s.Player.ChangeAudioListenerToObject(((Component)s.Player.gameplayCamera).gameObject); } } } public static void UpdateCameras() { if (Active.Count == 0) { return; } foreach (CocoonState value in Active.Values) { HideNameTag(value); if (!IsLocal(value.Player)) { DisableColliders(value); } for (int i = 0; i < value.Renderers.Count; i++) { if ((Object)(object)value.Renderers[i] != (Object)null && value.Renderers[i].enabled) { value.Renderers[i].enabled = false; } } if (value.CameraActive && IsLocal(value.Player)) { HideVisor(value.Player); } if (value.CameraActive) { try { UpdateCamera(value); } catch (Exception ex) { Plugin.Log.LogError((object)("Camera update failed, switching back: " + ex)); StopCamera(value, backToPlayer: true); } } } } private static void HideVisor(PlayerControllerB p) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)p == (Object)null) && !((Object)(object)p.localVisor == (Object)null) && !((Object)(object)instance == (Object)null) && !((Object)(object)instance.notSpawnedPosition == (Object)null)) { p.localVisor.position = instance.notSpawnedPosition.position; } } private static void HideNameTag(CocoonState s) { PlayerControllerB player = s.Player; if (!((Object)(object)player == (Object)null) && !IsLocal(player)) { if ((Object)(object)player.usernameAlpha != (Object)null) { player.usernameAlpha.alpha = 0f; } if ((Object)(object)player.usernameCanvas != (Object)null && ((Component)player.usernameCanvas).gameObject.activeSelf) { ((Component)player.usernameCanvas).gameObject.SetActive(false); } } } private static void UpdateCamera(CocoonState s) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Invalid comparison between Unknown and I4 //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: 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_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027a: 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_0142: 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_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; PlayerControllerB player = s.Player; if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null || (Object)(object)instance.spectateCamera == (Object)null || (Object)(object)player.deadBody == (Object)null || player.deadBody.bodyParts == null || player.deadBody.bodyParts.Length <= 6) { return; } Transform transform = ((Component)instance.spectateCamera).transform; Vector3 position = ((Component)player.deadBody.bodyParts[6]).transform.position; SandSpiderAI spider = s.Spider; if (!s.Hung && (Object)(object)spider != (Object)null && !((EnemyAI)spider).isEnemyDead && (Object)(object)spider.meshContainer != (Object)null) { Vector3 val = position - spider.meshContainer.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.25f) { s.CamDir = ((Vector3)(ref val)).normalized; } } Mouse current = Mouse.current; if (current != null && (int)Cursor.lockState == 1) { Vector2 val2 = ((InputControl<Vector2>)(object)((Pointer)current).delta).ReadValue(); float value = Plugin.LookSensitivity.Value; s.OrbitYaw += val2.x * value; s.OrbitPitch = Mathf.Clamp(s.OrbitPitch - val2.y * value, -50f, 70f); float y = ((InputControl<Vector2>)(object)current.scroll).ReadValue().y; if (Mathf.Abs(y) > 0.01f) { s.ZoomMul = Mathf.Clamp(s.ZoomMul - Mathf.Sign(y) * 0.15f, 0.5f, 2.5f); } } Vector3 val3 = Quaternion.AngleAxis(s.OrbitYaw, Vector3.up) * s.CamDir; float num = Mathf.Sqrt(13.690001f) * s.ZoomMul; float num2 = Mathf.Clamp(Mathf.Atan2(1.2f, 3.5f) * 57.29578f + s.OrbitPitch, -40f, 80f) * (MathF.PI / 180f); Vector3 val4 = val3 * (num * Mathf.Cos(num2)) + Vector3.up * (num * Mathf.Sin(num2)); Vector3 val5 = position + val4; RaycastHit val6 = default(RaycastHit); if (Physics.Raycast(position, ((Vector3)(ref val4)).normalized, ref val6, ((Vector3)(ref val4)).magnitude, instance.collidersAndRoomMask, (QueryTriggerInteraction)1)) { val5 = ((RaycastHit)(ref val6)).point - ((Vector3)(ref val4)).normalized * 0.25f; } float num3 = 1f - Mathf.Exp(-12f * Time.deltaTime); transform.position = (s.CamInitialized ? Vector3.Lerp(transform.position, val5, num3) : val5); Vector3 val7 = position - transform.position; if (((Vector3)(ref val7)).sqrMagnitude > 0.0001f) { Quaternion val8 = Quaternion.LookRotation(val7); transform.rotation = (s.CamInitialized ? Quaternion.Slerp(transform.rotation, val8, num3) : val8); } s.CamInitialized = true; } } internal static class CocoonNet { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequest; public static HandleNamedMessageDelegate <1>__OnRelease; } private const string RequestName = "SpiderCocoon.RequestRelease"; private const string ReleaseName = "SpiderCocoon.Release"; private static CustomMessagingManager registeredWith; private static bool reportedFailure; public static void EnsureRegistered() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0089: 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: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening) { registeredWith = null; return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null || customMessagingManager == registeredWith) { return; } try { object obj = <>O.<0>__OnRequest; if (obj == null) { HandleNamedMessageDelegate val = OnRequest; <>O.<0>__OnRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("SpiderCocoon.RequestRelease", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRelease; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnRelease; <>O.<1>__OnRelease = val2; obj2 = (object)val2; } customMessagingManager.RegisterNamedMessageHandler("SpiderCocoon.Release", (HandleNamedMessageDelegate)obj2); registeredWith = customMessagingManager; Plugin.Log.LogInfo((object)"Hung to Dry network messages registered."); } catch (Exception ex) { if (!reportedFailure) { reportedFailure = true; Plugin.Log.LogError((object)("Could not register network messages: " + ex)); } } } public unsafe static void RequestRelease(int victimId) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null) { return; } if (singleton.IsServer) { Broadcast(victimId); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteByteSafe((byte)victimId); singleton.CustomMessagingManager.SendNamedMessage("SpiderCocoon.RequestRelease", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void Broadcast(int victimId) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteByteSafe((byte)victimId); singleton.CustomMessagingManager.SendNamedMessageToAll("SpiderCocoon.Release", val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Cocoon.ApplyRelease(victimId); } private static void OnRequest(ulong senderClientId, FastBufferReader reader) { try { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer) { byte victimId = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref victimId); Broadcast(victimId); } } catch (Exception ex) { Plugin.Log.LogError((object)("Rescue request failed: " + ex)); } } private static void OnRelease(ulong senderClientId, FastBufferReader reader) { try { byte id = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref id); Cocoon.ApplyRelease(id); } catch (Exception ex) { Plugin.Log.LogError((object)("Rescue release failed: " + ex)); } } } [HarmonyPatch(typeof(PlayerControllerB), "ShowNameBillboard")] internal static class NameBadgePatch { private static bool Prefix(PlayerControllerB __instance) { return !Cocoon.IsCocooned(__instance); } } internal static class SpiderTargetPatch { internal static void Postfix(EnemyAI __instance, object[] __args, ref bool __result) { try { if (__result && __instance is SandSpiderAI && __args != null && __args.Length != 0) { object obj = __args[0]; PlayerControllerB player = (PlayerControllerB)((obj is PlayerControllerB) ? obj : null); if (Cocoon.IsCocooned(player) || Cocoon.IsImmune(player)) { __result = false; } } } catch (Exception) { } } } [HarmonyPatch(typeof(SandSpiderAI), "OnCollideWithPlayer")] internal static class SpiderAttackPatch { private static bool Prefix(SandSpiderAI __instance, Collider other, ref float ___timeSinceHittingPlayer, bool ___onWall, bool ___spoolingPlayerBody, DeadBodyInfo ___currentlyHeldBody) { if (((EnemyAI)__instance).isEnemyDead || ___onWall) { return false; } if ((Object)(object)___currentlyHeldBody != (Object)null) { return false; } PlayerControllerB val = ((EnemyAI)__instance).MeetsStandardPlayerCollisionConditions(other, ___spoolingPlayerBody, false); if ((Object)(object)val != (Object)null && !Cocoon.IsCocooned(val) && !Cocoon.IsImmune(val) && ___timeSinceHittingPlayer > 1f) { ___timeSinceHittingPlayer = 0f; Plugin.Log.LogInfo((object)"Spider hit intercepted: no damage, cocooning player."); __instance.HitPlayerServerRpc((int)GameNetworkManager.Instance.localPlayerController.playerClientId); } return false; } } [HarmonyPatch(typeof(SandSpiderAI), "HitPlayerClientRpc")] internal static class SpiderHitSyncPatch { private static void Postfix(SandSpiderAI __instance, int playerId) { try { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; if (playerId >= 0 && playerId < allPlayerScripts.Length) { Cocoon.Begin(allPlayerScripts[playerId], __instance); } } catch (Exception ex) { Plugin.Log.LogError((object)("SpiderHitSyncPatch failed: " + ex)); } } } [HarmonyPatch(typeof(SandSpiderAI), "HangBodyFromCeiling")] internal static class SpiderHangPatch { private static void Prefix(SandSpiderAI __instance, DeadBodyInfo ___currentlyHeldBody) { try { Cocoon.OnBodyHung(___currentlyHeldBody, __instance); } catch (Exception ex) { Plugin.Log.LogError((object)("SpiderHangPatch failed: " + ex)); } } } [HarmonyPatch(typeof(SandSpiderAI), "SpiderTurnBodyIntoWebClientRpc")] internal static class SpiderWrapRpcPatch { private static bool Prefix(SandSpiderAI __instance, DeadBodyInfo ___currentlyHeldBody) { try { if (((NetworkBehaviour)__instance).IsOwner || (Object)(object)___currentlyHeldBody != (Object)null) { return true; } CocoonRunner.Run(Cocoon.WrapWhenReady(__instance)); return false; } catch (Exception) { return true; } } } [HarmonyPatch(typeof(SandSpiderAI), "SpiderHangBodyClientRpc")] internal static class SpiderHangRpcPatch { private static bool Prefix(SandSpiderAI __instance, DeadBodyInfo ___currentlyHeldBody) { try { if (((NetworkBehaviour)__instance).IsOwner || (Object)(object)___currentlyHeldBody != (Object)null) { return true; } CocoonRunner.Run(Cocoon.HangWhenReady(__instance)); return false; } catch (Exception) { return true; } } } }