Decompiled source of CarryDeadFriends v1.0.1

CarryDeadFriends.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[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 CarryDeadFriends
{
	[BepInPlugin("yodawho.carrydeadfriends", "Carry Dead Friends", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				Harmony val = new Harmony("yodawho.carrydeadfriends");
				val.PatchAll();
				Log.LogInfo((object)"[CarryDeadFriends] Loaded fine.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"[CarryDeadFriends] Patch error: {arg}");
			}
		}
	}
	public class CarrySync : MonoBehaviour
	{
		internal PlayerDeathHead head;

		internal PhysGrabObject physObj;

		internal Transform originalParent;

		internal Transform targetBone;

		internal bool isBeingCarried;

		internal RigidbodyInterpolation originalInterpolation;

		private Coroutine reenableCollisionRoutine;

		private void Awake()
		{
			head = ((Component)this).GetComponent<PlayerDeathHead>();
			physObj = ((Component)this).GetComponent<PhysGrabObject>();
		}

		[PunRPC]
		public void CarryStartRPC(int carrierViewID)
		{
			PhotonView val = PhotonView.Find(carrierViewID);
			PlayerAvatar val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PlayerAvatar>() : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)head == (Object)null || (Object)(object)physObj == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[CarryDeadFriends] CarryStartRPC missing carrier/head/physObj.");
			}
			else
			{
				CarryManager.ApplyCarryVisuals(this, val2, head, physObj);
			}
		}

		[PunRPC]
		public void CarryEndRPC()
		{
			if (!((Object)(object)head == (Object)null) && !((Object)(object)physObj == (Object)null))
			{
				CarryManager.RemoveCarryVisuals(this, head, physObj);
			}
		}

		[PunRPC]
		public void SyncHeadPositionRPC(Vector3 pos, Quaternion rot)
		{
			//IL_0007: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = pos;
			((Component)this).transform.rotation = rot;
			if ((Object)(object)physObj != (Object)null && (Object)(object)physObj.rb != (Object)null)
			{
				physObj.rb.position = pos;
				physObj.rb.rotation = rot;
			}
		}

		public void IgnoreCollisionWithPlayerTemporarily(PlayerAvatar player, float duration)
		{
			if ((Object)(object)player == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[CarryDeadFriends] player null, skipping ignore collision.");
				return;
			}
			Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>();
			Collider[] componentsInChildren2 = ((Component)player).GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				Collider[] array2 = componentsInChildren2;
				foreach (Collider val2 in array2)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
					{
						Physics.IgnoreCollision(val, val2, true);
					}
				}
			}
			if (reenableCollisionRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(reenableCollisionRoutine);
				reenableCollisionRoutine = null;
			}
			reenableCollisionRoutine = ((MonoBehaviour)this).StartCoroutine(ReenableCollisionAfterDelay(componentsInChildren, componentsInChildren2, duration));
		}

		public IEnumerator ReenablePTVAfterDelay(PhotonTransformView ptv, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			if ((Object)(object)ptv != (Object)null)
			{
				((Behaviour)ptv).enabled = true;
			}
		}

		private IEnumerator ReenableCollisionAfterDelay(Collider[] headColliders, Collider[] playerColliders, float duration)
		{
			yield return (object)new WaitForSeconds(duration);
			foreach (Collider hc in headColliders)
			{
				foreach (Collider pc in playerColliders)
				{
					if ((Object)(object)hc != (Object)null && (Object)(object)pc != (Object)null)
					{
						Physics.IgnoreCollision(hc, pc, false);
					}
				}
			}
			reenableCollisionRoutine = null;
		}
	}
	public static class CarryManager
	{
		public static PlayerDeathHead CarriedHead = null;

		public static Transform TargetBone = null;

		private static readonly FieldInfo IsDisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled");

		private static readonly FieldInfo IsLocalField = AccessTools.Field(typeof(PlayerAvatar), "isLocal");

		private static readonly FieldInfo DeathHeadField = AccessTools.Field(typeof(PlayerAvatar), "playerDeathHead");

		private static readonly FieldInfo PhysGrabObjectField = AccessTools.Field(typeof(PlayerDeathHead), "physGrabObject");

		private static readonly FieldInfo LastPlayerGrabbingField = AccessTools.Field(typeof(PhysGrabObject), "lastPlayerGrabbing");

		private static readonly FieldInfo FrozenTimerField = AccessTools.Field(typeof(PhysGrabObject), "frozenTimer");

		private static readonly FieldInfo FrozenField = AccessTools.Field(typeof(PhysGrabObject), "frozen");

		private static readonly FieldInfo HeldByLocalPlayerField = AccessTools.Field(typeof(PhysGrabObject), "heldByLocalPlayer");

		private static readonly MethodInfo StartGrabbingPhysObjectMethod = AccessTools.Method(typeof(PhysGrabber), "StartGrabbingPhysObject", (Type[])null, (Type[])null);

		private static readonly FieldInfo GrabberMaskField = AccessTools.Field(typeof(PhysGrabber), "mask");

		private static readonly FieldInfo ToggleGrabField = AccessTools.Field(typeof(PhysGrabber), "toggleGrab");

		public static bool GetIsDisabled(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null || IsDisabledField == null)
			{
				return false;
			}
			object value = IsDisabledField.GetValue(player);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static IEnumerator SuppressGrabForceTemporarily(CarrySync sync, PhysGrabObject physObj, float duration)
		{
			float elapsed = 0f;
			while (elapsed < duration)
			{
				if ((Object)(object)physObj != (Object)null)
				{
					physObj.OverrideGrabForceZero();
				}
				elapsed += Time.deltaTime;
				yield return null;
			}
		}

		public static bool GetIsLocal(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null || IsLocalField == null)
			{
				return false;
			}
			object value = IsLocalField.GetValue(player);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static PlayerAvatar GetLocalPlayer()
		{
			List<PlayerAvatar> list = SemiFunc.PlayerGetList();
			if (list == null)
			{
				return null;
			}
			foreach (PlayerAvatar item in list)
			{
				if ((Object)(object)item != (Object)null && GetIsLocal(item))
				{
					return item;
				}
			}
			return null;
		}

		public static PlayerDeathHead GetPlayerDeathHead(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null || DeathHeadField == null)
			{
				return null;
			}
			object? value = DeathHeadField.GetValue(player);
			return (PlayerDeathHead)((value is PlayerDeathHead) ? value : null);
		}

		public static PhysGrabObject GetPhysGrabObject(PlayerDeathHead head)
		{
			if ((Object)(object)head == (Object)null || PhysGrabObjectField == null)
			{
				return null;
			}
			object? value = PhysGrabObjectField.GetValue(head);
			return (PhysGrabObject)((value is PhysGrabObject) ? value : null);
		}

		public static PlayerAvatar GetLastPlayerGrabbing(PhysGrabObject physObj)
		{
			if ((Object)(object)physObj == (Object)null || LastPlayerGrabbingField == null)
			{
				return null;
			}
			object? value = LastPlayerGrabbingField.GetValue(physObj);
			return (PlayerAvatar)((value is PlayerAvatar) ? value : null);
		}

		public static bool GetHeldByLocalPlayer(PhysGrabObject physObj)
		{
			if ((Object)(object)physObj == (Object)null || HeldByLocalPlayerField == null)
			{
				return false;
			}
			object value = HeldByLocalPlayerField.GetValue(physObj);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static void SetFrozen(PhysGrabObject physObj, bool state)
		{
			if (!((Object)(object)physObj == (Object)null) && !(FrozenField == null))
			{
				FrozenField.SetValue(physObj, state);
			}
		}

		public static void SetFrozenTimer(PhysGrabObject physObj, float value)
		{
			if (!((Object)(object)physObj == (Object)null) && !(FrozenTimerField == null))
			{
				FrozenTimerField.SetValue(physObj, value);
			}
		}

		private static Transform FindCarryBone(PlayerAvatar avatar)
		{
			Transform val = null;
			if ((Object)(object)avatar.playerAvatarVisuals != (Object)null)
			{
				Transform[] componentsInChildren = ((Component)avatar.playerAvatarVisuals).GetComponentsInChildren<Transform>();
				Transform[] array = componentsInChildren;
				foreach (Transform val2 in array)
				{
					string text = ((Object)val2).name.ToLower();
					if (text.Contains("chest") || text.Contains("spine") || text.Contains("torso") || text.Contains("body"))
					{
						val = val2;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)avatar).transform;
			}
			return val;
		}

		private static void PositionHeadOnBone(Transform headTransform, Transform bone)
		{
			//IL_0002: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			headTransform.localScale = Vector3.one;
			if ((Object)(object)bone == (Object)(object)bone.root || ((Object)bone).name.Contains("Player Avatar"))
			{
				headTransform.localPosition = new Vector3(0f, 1.4f, -0.35f);
			}
			else
			{
				headTransform.localPosition = new Vector3(0f, 0.65f, -0.35f);
			}
			Quaternion localRotation = Quaternion.Euler(-90f, 0f, 0f);
			((Quaternion)(ref localRotation)).Normalize();
			headTransform.localRotation = localRotation;
		}

		public static Transform ApplyCarryVisuals(CarrySync sync, PlayerAvatar carrier, PlayerDeathHead head, PhysGrabObject physObj)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			sync.originalParent = ((Component)head).transform.parent;
			sync.isBeingCarried = true;
			physObj.grabbed = false;
			physObj.grabbedLocal = false;
			if (HeldByLocalPlayerField != null)
			{
				HeldByLocalPlayerField.SetValue(physObj, false);
			}
			if (physObj.playerGrabbing != null)
			{
				physObj.playerGrabbing.Clear();
			}
			if ((Object)(object)physObj.rb != (Object)null)
			{
				physObj.rb.velocity = Vector3.zero;
				physObj.rb.angularVelocity = Vector3.zero;
				physObj.rb.isKinematic = true;
				physObj.rb.useGravity = false;
				sync.originalInterpolation = physObj.rb.interpolation;
				physObj.rb.interpolation = (RigidbodyInterpolation)0;
			}
			SetFrozen(physObj, state: true);
			Collider[] componentsInChildren = ((Component)head).GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				val.enabled = false;
			}
			Transform val2 = (sync.targetBone = FindCarryBone(carrier));
			((Component)head).transform.SetParent(val2);
			PositionHeadOnBone(((Component)head).transform, val2);
			PhotonTransformView component = ((Component)head).GetComponent<PhotonTransformView>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			return val2;
		}

		public static void RemoveCarryVisuals(CarrySync sync, PlayerDeathHead head, PhysGrabObject physObj)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			PhotonView component = ((Component)head).GetComponent<PhotonView>();
			if (sync.isBeingCarried)
			{
				sync.isBeingCarried = false;
				((Component)head).transform.SetParent(sync.originalParent);
				SetFrozen(physObj, state: false);
				SetFrozenTimer(physObj, 0f);
				if ((Object)(object)physObj.rb != (Object)null)
				{
					physObj.rb.isKinematic = false;
					physObj.rb.useGravity = true;
					physObj.rb.velocity = Vector3.zero;
					physObj.rb.angularVelocity = Vector3.zero;
					physObj.rb.interpolation = sync.originalInterpolation;
				}
				Collider[] componentsInChildren = ((Component)head).GetComponentsInChildren<Collider>();
				Collider[] array = componentsInChildren;
				foreach (Collider val in array)
				{
					val.enabled = true;
				}
				PhotonTransformView component2 = ((Component)head).GetComponent<PhotonTransformView>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Behaviour)component2).enabled = true;
				}
			}
		}

		public static PlayerDeathHead GetCurrentlyGrabbedDeadHead(PlayerAvatar localPlayer)
		{
			List<PlayerAvatar> list = SemiFunc.PlayerGetList();
			if (list == null)
			{
				return null;
			}
			foreach (PlayerAvatar item2 in list)
			{
				if ((Object)(object)item2 == (Object)null || !GetIsDisabled(item2))
				{
					continue;
				}
				PlayerDeathHead playerDeathHead = GetPlayerDeathHead(item2);
				if ((Object)(object)playerDeathHead == (Object)null)
				{
					continue;
				}
				PhysGrabObject physGrabObject = GetPhysGrabObject(playerDeathHead);
				if ((Object)(object)physGrabObject == (Object)null)
				{
					continue;
				}
				bool heldByLocalPlayer = GetHeldByLocalPlayer(physGrabObject);
				bool flag = physGrabObject.grabbedLocal || heldByLocalPlayer;
				bool grabbed = physGrabObject.grabbed;
				PlayerAvatar lastPlayerGrabbing = GetLastPlayerGrabbing(physGrabObject);
				bool flag2 = (Object)(object)lastPlayerGrabbing == (Object)(object)localPlayer;
				if (!flag2 && physGrabObject.playerGrabbing != null)
				{
					PhysGrabber[] componentsInChildren = ((Component)localPlayer).GetComponentsInChildren<PhysGrabber>();
					PhysGrabber[] array = componentsInChildren;
					foreach (PhysGrabber item in array)
					{
						if (physGrabObject.playerGrabbing.Contains(item))
						{
							flag2 = true;
							break;
						}
					}
				}
				if (!flag && !(grabbed && flag2))
				{
					continue;
				}
				return playerDeathHead;
			}
			return null;
		}

		public static void TryEquipHeadFromGrab(PlayerAvatar localPlayer)
		{
			if (!((Object)(object)CarriedHead != (Object)null))
			{
				PlayerDeathHead currentlyGrabbedDeadHead = GetCurrentlyGrabbedDeadHead(localPlayer);
				if (!((Object)(object)currentlyGrabbedDeadHead == (Object)null))
				{
					PickUpHead(localPlayer, currentlyGrabbedDeadHead);
				}
			}
		}

		private static CarrySync EnsureCarrySync(PlayerDeathHead head)
		{
			CarrySync carrySync = ((Component)head).GetComponent<CarrySync>();
			if ((Object)(object)carrySync == (Object)null)
			{
				carrySync = ((Component)head).gameObject.AddComponent<CarrySync>();
			}
			return carrySync;
		}

		private static void PickUpHead(PlayerAvatar localPlayer, PlayerDeathHead head)
		{
			PhysGrabObject physGrabObject = GetPhysGrabObject(head);
			if ((Object)(object)physGrabObject == (Object)null)
			{
				Plugin.Log.LogError((object)"[CarryDeadFriends] No PhysGrabObject on head, aborting pickup.");
				return;
			}
			CarrySync sync = EnsureCarrySync(head);
			Transform targetBone = ApplyCarryVisuals(sync, localPlayer, head, physGrabObject);
			CarriedHead = head;
			TargetBone = targetBone;
			PhotonView component = ((Component)head).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null)
			{
				component.RPC("CarryStartRPC", (RpcTarget)1, new object[1] { localPlayer.photonView.ViewID });
			}
			else
			{
				Plugin.Log.LogWarning((object)"[CarryDeadFriends] Head has no PhotonView, can't sync to others.");
			}
		}

		public static void UpdateHeadTransform()
		{
			if ((Object)(object)CarriedHead != (Object)null && (Object)(object)TargetBone != (Object)null)
			{
				PositionHeadOnBone(((Component)CarriedHead).transform, TargetBone);
			}
		}

		public static void ReturnHeadToGrab(PlayerAvatar localPlayer)
		{
			//IL_00aa: 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_00c5: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: 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_02d0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)CarriedHead == (Object)null)
			{
				return;
			}
			PhotonView component = ((Component)CarriedHead).GetComponent<PhotonView>();
			PhysGrabObject physGrabObject = GetPhysGrabObject(CarriedHead);
			PhysGrabber physGrabber = localPlayer.physGrabber;
			CarrySync component2 = ((Component)CarriedHead).GetComponent<CarrySync>();
			if ((Object)(object)physGrabber == (Object)null || (Object)(object)physGrabObject == (Object)null || (Object)(object)component2 == (Object)null || StartGrabbingPhysObjectMethod == null || GrabberMaskField == null)
			{
				Plugin.Log.LogError((object)"[CarryDeadFriends] Missing a reference, can't return to grab.");
				return;
			}
			Transform overrideTransform = localPlayer.localCamera.GetOverrideTransform();
			LayerMask val = (LayerMask)GrabberMaskField.GetValue(physGrabber);
			float num = Mathf.Min(physGrabber.grabRange, 2f);
			Vector3 position = overrideTransform.position;
			Vector3 forward = overrideTransform.forward;
			float num2 = num;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(position, forward, ref val2, num, LayerMask.op_Implicit(val), (QueryTriggerInteraction)1))
			{
				num2 = Mathf.Max(0.6f, ((RaycastHit)(ref val2)).distance - 0.15f);
			}
			Vector3 val3 = position + forward * num2;
			if ((Object)(object)component != (Object)null && !component.IsMine)
			{
				component.RPC("SyncHeadPositionRPC", (RpcTarget)2, new object[2]
				{
					val3,
					Quaternion.identity
				});
			}
			RemoveCarryVisuals(component2, CarriedHead, physGrabObject);
			if ((Object)(object)component != (Object)null && !component.IsMine)
			{
				PhotonTransformView component3 = ((Component)CarriedHead).GetComponent<PhotonTransformView>();
				if ((Object)(object)component3 != (Object)null)
				{
					((Behaviour)component3).enabled = false;
					((MonoBehaviour)component2).StartCoroutine(component2.ReenablePTVAfterDelay(component3, 0.2f));
				}
			}
			if ((Object)(object)component != (Object)null)
			{
				component.RPC("CarryEndRPC", (RpcTarget)1, Array.Empty<object>());
			}
			if ((Object)(object)physGrabObject.rb != (Object)null)
			{
				physGrabObject.rb.isKinematic = true;
				physGrabObject.rb.velocity = Vector3.zero;
				physGrabObject.rb.angularVelocity = Vector3.zero;
			}
			((Component)CarriedHead).transform.position = val3;
			((Component)CarriedHead).transform.rotation = Quaternion.identity;
			Physics.SyncTransforms();
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Raycast(position, forward, ref val4, num2 + 0.5f, LayerMask.op_Implicit(val), (QueryTriggerInteraction)1))
			{
				PhysGrabObject component4 = ((Component)((RaycastHit)(ref val4)).transform).GetComponent<PhysGrabObject>();
				if ((Object)(object)component4 == (Object)(object)physGrabObject)
				{
					if ((Object)(object)physGrabObject.rb != (Object)null)
					{
						physGrabObject.rb.isKinematic = false;
					}
					StartGrabbingPhysObjectMethod.Invoke(physGrabber, new object[2] { val4, component4 });
					if (ToggleGrabField != null)
					{
						ToggleGrabField.SetValue(physGrabber, true);
					}
					component2.IgnoreCollisionWithPlayerTemporarily(localPlayer, 3f);
					((MonoBehaviour)component2).StartCoroutine(SuppressGrabForceTemporarily(component2, physGrabObject, 1f));
					CarriedHead = null;
					TargetBone = null;
					return;
				}
			}
			Transform targetBone = ApplyCarryVisuals(component2, localPlayer, CarriedHead, physGrabObject);
			TargetBone = targetBone;
			if ((Object)(object)component != (Object)null)
			{
				component.RPC("CarryStartRPC", (RpcTarget)1, new object[1] { localPlayer.photonView.ViewID });
			}
		}
	}
	public class PlayerCarryController : MonoBehaviour
	{
		private PlayerAvatar localPlayer;

		private void Start()
		{
			localPlayer = ((Component)this).GetComponent<PlayerAvatar>();
		}

		private void Update()
		{
			if ((Object)(object)localPlayer != (Object)null && CarryManager.GetIsLocal(localPlayer))
			{
				if (Input.GetKeyDown((KeyCode)101))
				{
					CarryManager.TryEquipHeadFromGrab(localPlayer);
				}
				if (Input.GetKeyDown((KeyCode)122))
				{
					CarryManager.ReturnHeadToGrab(localPlayer);
				}
			}
		}

		private void LateUpdate()
		{
			if ((Object)(object)localPlayer != (Object)null && CarryManager.GetIsLocal(localPlayer) && (Object)(object)CarryManager.CarriedHead != (Object)null)
			{
				CarryManager.UpdateHeadTransform();
			}
		}
	}
	[HarmonyPatch(typeof(GoalUI))]
	public class CarryHudPatch
	{
		private const string HudText = "Carrying Dead Friend";

		private const string HudColorHex = "#ff9600";

		private const float HudFontSizeNormal = 20f;

		private const float HudFontSizePulseMax = 24f;

		private const float HudPulseSpeed = 6f;

		private const float HudOffsetBottom = 1f;

		private const float HudOffsetRight = 30f;

		private static bool hasPlayedReminderThisVisit = false;

		private static TextMeshProUGUI hudInstance;

		private static RoomVolumeCheck cachedRoomVolumeCheck;

		private static PlayerAvatar cachedPlayerForRoomCheck;

		private static AudioClip beepClip;

		private static readonly FieldInfo InExtractionPointField = AccessTools.Field(typeof(RoomVolumeCheck), "inExtractionPoint");

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void CustomPatch(ref TextMeshProUGUI ___Text)
		{
			if ((Object)(object)hudInstance == (Object)null)
			{
				CreateHud(___Text);
				if ((Object)(object)hudInstance == (Object)null)
				{
					return;
				}
			}
			UpdateRoomVolumeCheckCache();
			bool flag = (Object)(object)CarryManager.CarriedHead != (Object)null;
			((Component)hudInstance).gameObject.SetActive(flag);
			if (!flag)
			{
				return;
			}
			if (IsLocalPlayerInExtractionRoom())
			{
				float num = Mathf.PingPong(Time.time * 6f, 4f);
				((TMP_Text)hudInstance).fontSize = 20f + num;
				if (!hasPlayedReminderThisVisit)
				{
					hasPlayedReminderThisVisit = true;
					PlayReminderBeep();
				}
			}
			else
			{
				((TMP_Text)hudInstance).fontSize = 20f;
				hasPlayedReminderThisVisit = false;
			}
		}

		private static void UpdateRoomVolumeCheckCache()
		{
			PlayerAvatar localPlayer = CarryManager.GetLocalPlayer();
			if (!((Object)(object)localPlayer == (Object)null) && ((Object)(object)cachedRoomVolumeCheck == (Object)null || (Object)(object)cachedPlayerForRoomCheck != (Object)(object)localPlayer))
			{
				cachedRoomVolumeCheck = ((Component)localPlayer).GetComponentInChildren<RoomVolumeCheck>();
				cachedPlayerForRoomCheck = localPlayer;
				if ((Object)(object)cachedRoomVolumeCheck == (Object)null)
				{
					cachedRoomVolumeCheck = Object.FindObjectOfType<RoomVolumeCheck>();
				}
			}
		}

		private static bool IsLocalPlayerInExtractionRoom()
		{
			if ((Object)(object)cachedRoomVolumeCheck == (Object)null)
			{
				return false;
			}
			List<RoomVolume> currentRooms = cachedRoomVolumeCheck.CurrentRooms;
			if (currentRooms == null || currentRooms.Count == 0)
			{
				return false;
			}
			Module val = null;
			foreach (RoomVolume item in currentRooms)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item.Module != (Object)null)
				{
					val = item.Module;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			bool result = false;
			RoomVolume[] array = Object.FindObjectsOfType<RoomVolume>();
			RoomVolume[] array2 = array;
			foreach (RoomVolume val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.Module == (Object)(object)val && val2.Extraction)
				{
					result = true;
					break;
				}
			}
			return result;
		}

		private static void PlayReminderBeep()
		{
			//IL_001d: 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_0022: 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)
			PlayerAvatar localPlayer = CarryManager.GetLocalPlayer();
			Vector3 val = (((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).transform.position : Vector3.zero);
			AudioSource.PlayClipAtPoint(GetBeepClip(), val, 0.6f);
		}

		public static void TestPlayBeep(Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			AudioSource.PlayClipAtPoint(GetBeepClip(), position, 0.6f);
		}

		private static AudioClip GetBeepClip()
		{
			if ((Object)(object)beepClip != (Object)null)
			{
				return beepClip;
			}
			int num = 44100;
			float num2 = 0.15f;
			int num3 = Mathf.CeilToInt((float)num * num2);
			float num4 = 880f;
			float[] array = new float[num3];
			for (int i = 0; i < num3; i++)
			{
				array[i] = Mathf.Sin(MathF.PI * 2f * num4 * (float)i / (float)num) * 0.5f;
			}
			beepClip = AudioClip.Create("CarryDeadFriends_Beep", num3, 1, num, false);
			beepClip.SetData(array, 0);
			return beepClip;
		}

		private static void CreateHud(TextMeshProUGUI sourceText)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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)
			Transform parent = ((TMP_Text)sourceText).transform.parent;
			if (!((Object)(object)parent == (Object)null))
			{
				GameObject val = new GameObject("CarryDeadFriends_HUD", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(parent, false);
				TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
				((TMP_Text)val2).font = ((TMP_Text)sourceText).font;
				((TMP_Text)val2).fontSharedMaterial = ((TMP_Text)sourceText).fontSharedMaterial;
				((TMP_Text)val2).fontSize = 20f;
				((TMP_Text)val2).alignment = (TextAlignmentOptions)1028;
				((TMP_Text)val2).text = "<color=#ff9600>Carrying Dead Friend</color>";
				((Graphic)val2).color = Color.white;
				((Graphic)val2).raycastTarget = false;
				RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
				rectTransform.anchorMin = new Vector2(1f, 0f);
				rectTransform.anchorMax = new Vector2(1f, 0f);
				rectTransform.pivot = new Vector2(1f, 0f);
				rectTransform.anchoredPosition = new Vector2(-30f, 1f);
				rectTransform.sizeDelta = new Vector2(400f, 40f);
				((Transform)rectTransform).localScale = Vector3.one;
				val.SetActive(false);
				hudInstance = val2;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar))]
	public class PlayerAvatarPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void StartPostfix(PlayerAvatar __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && (Object)(object)((Component)__instance).GetComponent<PlayerCarryController>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<PlayerCarryController>();
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "FixedUpdate")]
	public class PhysGrabObjectFixedUpdatePatch
	{
		[HarmonyPrefix]
		public static void FixedUpdatePrefix(PhysGrabObject __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<CarrySync>() != (Object)null))
			{
				PlayerDeathHead component = ((Component)__instance).GetComponent<PlayerDeathHead>();
				if ((Object)(object)component != (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<CarrySync>();
				}
			}
		}
	}
}