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 CarryDeadFriends v1.0.1
CarryDeadFriends.dll
Decompiled 2 weeks agousing 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>(); } } } } }