using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FirstPersonView.Compat; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FirstPersonView")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Lets players see their own body.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+058a0c624f188a4e010b55984f0e2cc89f58d0f4")] [assembly: AssemblyProduct("FirstPersonView")] [assembly: AssemblyTitle("FirstPersonView")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 FirstPersonView { internal static class CameraRig { public static void ApplyOffset(LocalBodyState state, PlayerControllerB player) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0234: 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_022b: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0246: 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_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: 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_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: 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_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) Camera gameplayCamera = state.GameplayCamera; if (!((Object)(object)gameplayCamera == (Object)null) && state.CameraBaseCaptured) { Transform transform = ((Component)gameplayCamera).transform; Transform parent = transform.parent; Vector3 val = (((Object)(object)parent != (Object)null) ? parent.up : Vector3.up); Vector3 val2 = Vector3.ProjectOnPlane(transform.forward, val); if (((Vector3)(ref val2)).sqrMagnitude < 1E-05f) { val2 = Vector3.ProjectOnPlane(((Component)player).transform.forward, val); } val2 = ((!(((Vector3)(ref val2)).sqrMagnitude < 1E-05f)) ? ((Vector3)(ref val2)).normalized : (((Object)(object)parent != (Object)null) ? parent.forward : Vector3.forward)); Vector3 val3 = Vector3.Cross(val, val2); Quaternion yawRotation = Quaternion.LookRotation(val2, val); state.CrouchBlend = Mathf.MoveTowards(state.CrouchBlend, player.isCrouching ? 1f : 0f, Time.deltaTime / 0.15f); state.HoldBlend = Mathf.MoveTowards(state.HoldBlend, Players.IsHoldingTwoHanded(player) ? 1f : 0f, Time.deltaTime / 0.18f); state.RunBlend = Mathf.MoveTowards(state.RunBlend, player.isSprinting ? 1f : 0f, Time.deltaTime / 0.18f); state.JumpBlend = Mathf.MoveTowards(state.JumpBlend, (player.isJumping || player.isFallingFromJump) ? 1f : 0f, Time.deltaTime / 0.18f); float num = 0f + state.CrouchBlend * 0.12f + state.HoldBlend * 0.07f + state.RunBlend * 0.05f + state.JumpBlend * 0f; state.LadderBlend = Mathf.MoveTowards(state.LadderBlend, player.isClimbingLadder ? 1f : 0f, Time.deltaTime / 0.08f); float num2 = Mathf.Lerp(0.13f, 0f, state.LadderBlend) + state.HoldBlend * 0.15f + state.RunBlend * 0.1f + state.JumpBlend * 0.13f; Vector3 val4 = (((Object)(object)parent != (Object)null) ? parent.TransformPoint(state.CameraBaseLocalPosition) : state.CameraBaseLocalPosition); Vector3 val5 = FollowBodyAnchor(state, player, val4, yawRotation); Vector3 desired = val5 + val2 * num2 + val3 * 0f + val * num; desired = (transform.position = ResolveWallCollision(val4, desired)); state.LastCameraTargetLocal = (((Object)(object)parent != (Object)null) ? parent.InverseTransformPoint(desired) : desired); state.HasCameraTarget = true; state.CameraOffsetApplied = true; } } public static void RelaxSeatedLookClamp(PlayerControllerB player) { if (player.inVehicleAnimation && player.clampLooking && player.minVerticalClamp < 75f) { player.minVerticalClamp = 75f; } } public static void AlignForInteractionRay(LocalBodyState state) { //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_0035: Unknown result type (might be due to invalid IL or missing references) if (state.HasCameraTarget && !((Object)(object)state.GameplayCamera == (Object)null)) { Transform transform = ((Component)state.GameplayCamera).transform; Transform parent = transform.parent; transform.position = (((Object)(object)parent != (Object)null) ? parent.TransformPoint(state.LastCameraTargetLocal) : state.LastCameraTargetLocal); } } public static void ApplyArmAnchor(PlayerControllerB player, bool useVanillaArms) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) if (!useVanillaArms || player.inSpecialInteractAnimation) { return; } Transform localArmsTransform = player.localArmsTransform; Camera gameplayCamera = player.gameplayCamera; Transform cameraContainerTransform = player.cameraContainerTransform; if (!((Object)(object)localArmsTransform == (Object)null) && !((Object)(object)gameplayCamera == (Object)null) && !((Object)(object)cameraContainerTransform == (Object)null)) { Transform transform = ((Component)gameplayCamera).transform; localArmsTransform.position += transform.position - cameraContainerTransform.position; float value = ConfigManager.HandOffsetZ.Value; if (value != 0f) { localArmsTransform.position += transform.forward * value; } } } private static Vector3 FollowBodyAnchor(LocalBodyState state, PlayerControllerB player, Vector3 baseWorld, Quaternion yawRotation) { //IL_0010: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) Transform headBone = state.HeadBone; if ((Object)(object)headBone == (Object)null) { return baseWorld; } if (!state.EyeAnchorCaptured) { state.EyeAnchorLocal = Quaternion.Inverse(yawRotation) * (baseWorld - headBone.position); state.EyeAnchorBoneLocal = headBone.InverseTransformPoint(baseWorld); state.EyeAnchorCaptured = true; } if (TooManyEmotesCompat.IsFirstPersonEmoteActive()) { return headBone.TransformPoint(state.EyeAnchorBoneLocal); } Vector3 val = headBone.position + yawRotation * state.EyeAnchorLocal; Vector3 val2 = Quaternion.Inverse(yawRotation) * (val - baseWorld); val2.x *= 1f; val2.z *= 1f; val2.y *= 1f; val2.y = DampHeadBob(state, player, val2.y); val2 = StabilizeSprintBob(state, player, val2); val2 = NeckGuardedFollow(state, player, val2); if (((Vector3)(ref val2)).sqrMagnitude > 0.25f) { val2 = ((Vector3)(ref val2)).normalized * 0.5f; } return baseWorld + yawRotation * val2; } private static float DampHeadBob(LocalBodyState state, PlayerControllerB player, float rawY) { if (!state.DisableBobSmoothInitialized) { state.DisableBobSmoothedY = rawY; state.DisableBobSmoothInitialized = true; } else { float num = 1f - Mathf.Exp((0f - Time.deltaTime) / 1f); state.DisableBobSmoothedY = Mathf.Lerp(state.DisableBobSmoothedY, rawY, num); } bool flag = ConfigManager.DisableHeadBob.Value && !player.isCrouching && state.CrouchBlend <= 0f && (player.isWalking || player.isSprinting || player.isJumping || player.isFallingFromJump); state.DisableBobBlend = Mathf.MoveTowards(state.DisableBobBlend, flag ? 1f : 0f, Time.deltaTime / 0.15f); return Mathf.Lerp(rawY, state.DisableBobSmoothedY, state.DisableBobBlend); } private static Vector3 StabilizeSprintBob(LocalBodyState state, PlayerControllerB player, Vector3 deviationLocal) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) bool flag = player.isSprinting || player.isJumping || player.isFallingFromJump; state.BobDampBlend = Mathf.MoveTowards(state.BobDampBlend, flag ? 1f : 0f, Time.deltaTime / 0.12f); if (!state.DeviationSmoothInitialized) { state.SmoothedDeviationLocal = deviationLocal; state.DeviationSmoothInitialized = true; } else { float num = 1f - Mathf.Exp((0f - Time.deltaTime) / 0.2f); state.SmoothedDeviationLocal = Vector3.Lerp(state.SmoothedDeviationLocal, deviationLocal, num); } float num2 = state.BobDampBlend * 0.6f; return Vector3.Lerp(deviationLocal, state.SmoothedDeviationLocal, num2); } private static Vector3 NeckGuardedFollow(LocalBodyState state, PlayerControllerB player, Vector3 live) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) if (!state.NeckGuardInitialized) { state.SwingRest = live; state.GuardedEyeDeviation = live; state.GuardedEyeVelocity = Vector3.zero; state.NeckGuardTail = 0f; state.NeckGuardRelease = 0f; state.NeckGuardLatched = false; state.NeckGuardWasSwinging = false; state.NeckGuardEngaged = false; state.NeckGuardFloorActive = false; state.NeckGuardCrouchRestZ = live.z; state.NeckGuardCrouchRestY = live.y; state.NeckGuardInitialized = true; return live; } bool flag = player.isCrouching && player.activatingItem; if (flag && !state.NeckGuardWasSwinging) { state.NeckGuardLatched = state.CrouchBlend >= 0.9f; } state.NeckGuardWasSwinging = flag; if (flag) { state.NeckGuardTail = 0.6f; } else if (state.NeckGuardTail > 0f) { state.NeckGuardTail -= Time.deltaTime; } bool flag2 = flag || state.NeckGuardTail > 0f; bool flag3 = state.NeckGuardLatched && player.isCrouching && flag2; if (player.isCrouching && !flag2) { state.NeckGuardCrouchRestZ = live.z; state.NeckGuardCrouchRestY = live.y; } bool flag4 = flag2 && player.isCrouching && !state.NeckGuardLatched; if (flag4 && !state.NeckGuardFloorActive) { state.NeckGuardFloorZ = Mathf.Max(state.NeckGuardCrouchRestZ, 0.35f); state.NeckGuardFloorActive = true; } else if (!flag4) { state.NeckGuardFloorActive = false; } if (state.NeckGuardEngaged && !flag3 && !flag4) { state.NeckGuardRelease = 0.8f; } else if (state.NeckGuardRelease > 0f) { state.NeckGuardRelease -= Time.deltaTime; } state.NeckGuardEngaged = flag3 || flag4; if (!flag3) { state.SwingRest = live; } Vector3 swingRest = state.SwingRest; Vector3 val = live; if (flag3) { val.z = Mathf.Max(live.z, swingRest.z); if (flag) { val.y = ((live.y >= swingRest.y) ? (swingRest.y + (live.y - swingRest.y) * 1f) : (swingRest.y + (live.y - swingRest.y) * 0f)); } else { val.y = swingRest.y; } } else if (state.NeckGuardFloorActive) { val.z = Mathf.Max(live.z, state.NeckGuardFloorZ); float neckGuardCrouchRestY = state.NeckGuardCrouchRestY; val.y = ((!flag) ? neckGuardCrouchRestY : ((live.y >= neckGuardCrouchRestY) ? (neckGuardCrouchRestY + (live.y - neckGuardCrouchRestY) * 1f) : (neckGuardCrouchRestY + (live.y - neckGuardCrouchRestY) * 0f))); } bool flag5 = flag3 || (flag2 && player.isCrouching); float num = (flag5 ? 0.12f : ((!(state.NeckGuardRelease > 0f)) ? 0.015f : Mathf.Lerp(0.015f, 0.12f, state.NeckGuardRelease / 0.8f))); float num2 = (flag5 ? 0.12f : 0.015f); float x = state.GuardedEyeVelocity.x; float y = state.GuardedEyeVelocity.y; float z = state.GuardedEyeVelocity.z; state.GuardedEyeDeviation = new Vector3(Mathf.SmoothDamp(state.GuardedEyeDeviation.x, val.x, ref x, num), Mathf.SmoothDamp(state.GuardedEyeDeviation.y, val.y, ref y, num2), Mathf.SmoothDamp(state.GuardedEyeDeviation.z, val.z, ref z, num)); state.GuardedEyeVelocity = new Vector3(x, y, z); return state.GuardedEyeDeviation; } private static Vector3 ResolveWallCollision(Vector3 origin, Vector3 desired) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return desired; } Vector3 val = desired - origin; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.0001f) { return desired; } Vector3 val2 = val / magnitude; float num = Mathf.Max(0.01f, 0.11f); RaycastHit val3 = default(RaycastHit); if (Physics.SphereCast(origin, num, val2, ref val3, magnitude, instance.collidersAndRoomMask, (QueryTriggerInteraction)1)) { float num2 = Mathf.Clamp(((RaycastHit)(ref val3)).distance, 0f, magnitude); return origin + val2 * num2; } return desired; } public static void RestoreOffset(LocalBodyState state) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) state.CrouchBlend = 0f; state.LadderBlend = 0f; state.BobDampBlend = 0f; state.HoldBlend = 0f; state.RunBlend = 0f; state.JumpBlend = 0f; state.NeckGuardInitialized = false; state.NeckGuardTail = 0f; state.NeckGuardRelease = 0f; state.NeckGuardFloorActive = false; state.DeviationSmoothInitialized = false; state.DisableBobSmoothInitialized = false; state.DisableBobBlend = 0f; state.HasCameraTarget = false; if (state.CameraOffsetApplied) { Camera gameplayCamera = state.GameplayCamera; if ((Object)(object)gameplayCamera != (Object)null && state.CameraBaseCaptured) { ((Component)gameplayCamera).transform.localPosition = state.CameraBaseLocalPosition; } state.CameraOffsetApplied = false; } } } internal static class VisorRig { private static bool? immersiveVisorPresent; public static bool IsImmersiveVisorPresent() { bool valueOrDefault = immersiveVisorPresent == true; if (!immersiveVisorPresent.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("ImmersiveVisor"); immersiveVisorPresent = valueOrDefault; } return immersiveVisorPresent.Value; } public static void StickToCamera(LocalBodyState state) { if (!state.VisorReparented) { Transform localVisor = state.LocalVisor; Camera gameplayCamera = state.GameplayCamera; if (!((Object)(object)localVisor == (Object)null) && !((Object)(object)gameplayCamera == (Object)null)) { localVisor.SetParent(((Component)gameplayCamera).transform, true); state.VisorReparented = true; } } } public static void Restore(LocalBodyState state) { if (state.VisorReparented) { if ((Object)(object)state.LocalVisor != (Object)null && state.VisorOriginalParentCaptured) { state.LocalVisor.SetParent(state.VisorOriginalParent, true); } state.VisorReparented = false; } } public static void SuppressVanillaCrack(LocalBodyState state, bool hide) { if (hide == state.CrackHidden) { return; } if (state.CrackRenderers == null) { GameObject val = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.visorCracksObject : null); if ((Object)(object)val == (Object)null) { return; } state.CrackRenderers = val.GetComponentsInChildren(true); } Renderer[] crackRenderers = state.CrackRenderers; foreach (Renderer val2 in crackRenderers) { if ((Object)(object)val2 != (Object)null) { val2.enabled = !hide; } } state.CrackHidden = hide; } } public static class ConfigManager { public static ConfigEntry HeldItemFadeStyle; public static ConfigEntry Hands; public static ConfigEntry ItemDither; public static ConfigEntry HandOffsetZ; public static ConfigEntry DisableHeadBob; public static ConfigEntry EnableMoreCompanyCompatibility; public static ConfigEntry EnableTooManyEmotesCompatibility; public static ConfigEntry ShowMoreCompanyHat; public static ConfigEntry ShowMoreCompanyChest; public static ConfigEntry ShowMoreCompanyHip; public static ConfigEntry ShowMoreCompanyRightLowerArm; public static ConfigEntry ShowMoreCompanyLeftShin; public static ConfigEntry ShowMoreCompanyRightShin; internal static void Initialize(ConfigFile config) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown EnableMoreCompanyCompatibility = config.Bind("1. Compatibility", "Enable MoreCompany Compatibility", true, "Show your MoreCompany cosmetics in first person when MoreCompany is installed."); EnableTooManyEmotesCompatibility = config.Bind("1. Compatibility", "Enable TooManyEmotes Compatibility", true, "Keep the camera on your head during a TooManyEmotes first-person emote. Takes effect on restart."); ShowMoreCompanyHat = config.Bind("1. Compatibility", "ShowHat", false, "Show hat cosmetics. False by default to prevent hats from clipping into the camera."); ShowMoreCompanyChest = config.Bind("1. Compatibility", "ShowChest", true, "Show chest cosmetics."); ShowMoreCompanyHip = config.Bind("1. Compatibility", "ShowHip", true, "Show hip cosmetics."); ShowMoreCompanyRightLowerArm = config.Bind("1. Compatibility", "ShowRightLowerArm", true, "Show right lower arm cosmetics."); ShowMoreCompanyLeftShin = config.Bind("1. Compatibility", "ShowLeftShin", true, "Show left shin cosmetics."); ShowMoreCompanyRightShin = config.Bind("1. Compatibility", "ShowRightShin", true, "Show right shin cosmetics."); HeldItemFadeStyle = config.Bind("2. Held Item", "FadeMode", HeldItemFadeMode.Dither, "Held item will start to dither when it is close to or filling the players camera. Dither: a fade that lets you see through the item. Off: nothing dithers."); ItemDither = config.Bind("2. Held Item", "ItemDither", ItemDitherMode.ThirdPerson, "Which hands mode the held item dithers in."); HandOffsetZ = config.Bind("2. Held Item", "HandOffsetZ", 0f, new ConfigDescription("First-person hand offset.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); Hands = config.Bind("3. Hands", "HandsMode", HandsMode.Vanilla, "Which arms hold an item in first person. Vanilla: real first-person arms that aim the item with the camera [ recommended ]. ThirdPerson: the body own arms hold the item, more consistent body, but with known issues."); DisableHeadBob = config.Bind("4. Camera", "DisableHeadBob", false, "Disable head bobbing from walking and running animations."); } } internal static class Constants { public const string ScavengerModelName = "ScavengerModel"; public const string MetarigName = "metarig"; public const string HeadBoneName = "spine.004"; public const string LeftArmBoneName = "shoulder.L"; public const string RightArmBoneName = "shoulder.R"; public const int EnemiesNotRenderedLayer = 23; public static readonly string[] HeadBoneNameHints = new string[4] { "head", "helmet", "visor", "spine.004" }; public const float HeadStrongInfluenceThreshold = 0.35f; public const float HeadAverageInfluenceThreshold = 0.3f; public const float PipeCullBehindThreshold = 0f; public const float CrouchBlendTime = 0.15f; public const float LadderBlendTime = 0.08f; public const float BobDampBlendTime = 0.12f; public const float BobStabilizeTau = 0.2f; public const float DisableHeadBobTau = 1f; public const float DisableHeadBobBlendTime = 0.15f; public const float NeckGuardCalmTau = 0.015f; public const float NeckGuardSwingTau = 0.12f; public const float NeckGuardSwingTail = 0.6f; public const float NeckGuardReleaseRamp = 0.8f; public const float NeckGuardUpFollow = 1f; public const float NeckGuardDownFollow = 0f; public const float NeckGuardCrouchSettled = 0.9f; public const float NeckGuardCrouchFloor = 0.35f; public const float FollowStrengthVertical = 1f; public const float FollowStrengthHorizontal = 1f; public const float SprintBobReduction = 0.6f; public const float MaxFollowOffset = 0.5f; public const float EyeOffsetForward = 0.13f; public const float EyeOffsetForwardOnLadder = 0f; public const float EyeOffsetUp = 0f; public const float EyeOffsetRight = 0f; public const float CrouchEyeOffsetUp = 0.12f; public const float HoldingEyeOffsetForward = 0.15f; public const float HoldingEyeOffsetUp = 0.07f; public const float HoldingBlendTime = 0.18f; public const float RunningEyeOffsetForward = 0.1f; public const float RunningEyeOffsetUp = 0.05f; public const float RunningBlendTime = 0.18f; public const float JumpingEyeOffsetForward = 0.13f; public const float JumpingEyeOffsetUp = 0f; public const float JumpingBlendTime = 0.18f; public const bool EnableWallCollision = true; public const float WallCollisionRadius = 0.11f; public const float HeldItemFadeStartDistance = 0.35f; public const float HeldItemFadeEndDistance = 0.1f; public const float HeldItemCoverageFadeStart = 0.45f; public const float HeldItemCoverageFadeFull = 0.6f; public const float HeldItemMinFade = 0.11f; public const float HeldItemFadeSmoothTime = 0.08f; public const float SeatedLookDownClamp = 75f; public static readonly Vector3 CruiserKeyPositionOffset = new Vector3(0f, 0f, -0.05f); public static readonly Vector3 CruiserKeyRotationOffset = Vector3.zero; } public enum HandsMode { Vanilla, ThirdPerson } public enum HeldItemFadeMode { Dither, Off } [Flags] public enum ItemDitherMode { Vanilla = 1, ThirdPerson = 2 } internal sealed class LocalBodyState { public PlayerControllerB Player; public Transform ModelRoot; public Transform? HeadBone; public SkinnedMeshRenderer? BodyRenderer; public Mesh? OriginalBodyMesh; public bool OriginalBodyMeshCaptured; public bool HeadHidden; public SkinnedMeshRenderer? ShadowProxy; public Transform? LeftArmBone; public Transform? RightArmBone; public Transform? LocalVisor; public Transform? VisorOriginalParent; public bool VisorOriginalParentCaptured; public bool VisorReparented; public Renderer[]? CrackRenderers; public bool CrackHidden; public Camera? GameplayCamera; public Vector3 CameraBaseLocalPosition; public bool CameraBaseCaptured; public bool CameraOffsetApplied; public Vector3 LastCameraTargetLocal; public bool HasCameraTarget; public float CrouchBlend; public float LadderBlend; public float BobDampBlend; public float HoldBlend; public float RunBlend; public float JumpBlend; public Vector3 SmoothedDeviationLocal; public bool DeviationSmoothInitialized; public float DisableBobSmoothedY; public bool DisableBobSmoothInitialized; public float DisableBobBlend; public Vector3 SwingRest; public Vector3 GuardedEyeDeviation; public Vector3 GuardedEyeVelocity; public float NeckGuardTail; public float NeckGuardRelease; public float NeckGuardFloorZ; public float NeckGuardCrouchRestZ; public float NeckGuardCrouchRestY; public bool NeckGuardFloorActive; public bool NeckGuardInitialized; public bool NeckGuardLatched; public bool NeckGuardWasSwinging; public bool NeckGuardEngaged; public Vector3 EyeAnchorLocal; public Vector3 EyeAnchorBoneLocal; public bool EyeAnchorCaptured; } internal static class LocalBodyViewController { private static readonly Dictionary States = new Dictionary(); private static bool renderCallbacksHooked; internal static bool LocalBodyShown; private static readonly (Action Apply, Action Restore)[] CameraPasses = new(Action, Action)[2] { (FirstPersonBody.ApplyForCamera, FirstPersonBody.RestoreAfterCamera), (HeldItemView.ApplyForCamera, HeldItemView.RestoreAfterCamera) }; public static void ResetAllStates() { foreach (LocalBodyState value in States.Values) { FirstPersonBody.RestoreHead(value); VisorRig.Restore(value); CameraRig.RestoreOffset(value); if ((Object)(object)value.ShadowProxy != (Object)null) { Object.Destroy((Object)(object)((Component)value.ShadowProxy).gameObject); } } States.Clear(); LocalBodyShown = false; FirstPersonBody.Reset(); HeldItemView.Reset(); MeshSurgery.ClearCaches(); if (renderCallbacksHooked) { RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; renderCallbacksHooked = false; } } public static void Tick(PlayerControllerB player) { if (Players.IsLocal(player)) { EnsureRenderCallbacksHooked(); LocalBodyState orCreateState = GetOrCreateState(player); if (NeedsRefresh(orCreateState, player)) { RefreshState(orCreateState, player); } bool flag = (LocalBodyShown = player.isPlayerControlled && !player.isPlayerDead); bool flag2 = flag && Players.IsActivelyHolding(player) && !player.inSpecialInteractAnimation && ConfigManager.Hands.Value == HandsMode.Vanilla; FirstPersonBody.ApplyBodyRendering(orCreateState, flag, flag2); FirstPersonBody.ApplyFirstPersonCameraLayer(orCreateState, flag); HeldItemView.ApplyHolder(orCreateState, player, flag, flag2); if (flag) { FirstPersonBody.HideHead(orCreateState, flag2); } else { FirstPersonBody.RestoreHead(orCreateState); } if (flag && !VisorRig.IsImmersiveVisorPresent()) { VisorRig.StickToCamera(orCreateState); } else { VisorRig.Restore(orCreateState); } VisorRig.SuppressVanillaCrack(orCreateState, VisorRig.IsImmersiveVisorPresent()); if (flag && !player.inTerminalMenu) { CameraRig.ApplyOffset(orCreateState, player); } else { CameraRig.RestoreOffset(orCreateState); } CameraRig.ApplyArmAnchor(player, flag2); CameraRig.RelaxSeatedLookClamp(player); MoreCompanyCompat.ApplyLocalCosmeticVisibility(player, flag, flag2); } } public static void AlignCameraForInteractionRay(PlayerControllerB player) { if (Players.IsLocal(player) && States.TryGetValue(((Object)player).GetInstanceID(), out LocalBodyState value)) { CameraRig.AlignForInteractionRay(value); } } private static LocalBodyState GetOrCreateState(PlayerControllerB player) { int instanceID = ((Object)player).GetInstanceID(); if (!States.TryGetValue(instanceID, out LocalBodyState value)) { value = new LocalBodyState(); States[instanceID] = value; } return value; } private static bool NeedsRefresh(LocalBodyState state, PlayerControllerB player) { if (!((Object)(object)state.Player != (Object)(object)player) && !((Object)(object)state.ModelRoot == (Object)null) && !((Object)(object)state.HeadBone == (Object)null)) { return (Object)(object)state.BodyRenderer == (Object)null; } return true; } private static void RefreshState(LocalBodyState state, PlayerControllerB player) { state.Player = player; Transform val = ((Component)player).transform.Find("ScavengerModel"); state.ModelRoot = (((Object)(object)val != (Object)null) ? val : ((Component)player).transform); state.HeadBone = FindHeadBone(state.ModelRoot, player); state.LeftArmBone = FindBodyBone(player, "shoulder.L"); state.RightArmBone = FindBodyBone(player, "shoulder.R"); state.BodyRenderer = player.thisPlayerModel; CaptureOriginalBodyMesh(state); state.LocalVisor = player.localVisor; CaptureVisorOriginalParent(state); state.GameplayCamera = player.gameplayCamera; CaptureCameraBase(state); } private static void CaptureOriginalBodyMesh(LocalBodyState state) { if (!((Object)(object)state.BodyRenderer == (Object)null) && !state.OriginalBodyMeshCaptured && !state.HeadHidden) { Mesh sharedMesh = state.BodyRenderer.sharedMesh; if (!((Object)(object)sharedMesh == (Object)null) && !MeshSurgery.IsGenerated(((Object)sharedMesh).GetInstanceID())) { state.OriginalBodyMesh = sharedMesh; state.OriginalBodyMeshCaptured = true; } } } private static void CaptureVisorOriginalParent(LocalBodyState state) { if (!((Object)(object)state.LocalVisor == (Object)null) && !state.VisorOriginalParentCaptured && !state.VisorReparented) { state.VisorOriginalParent = state.LocalVisor.parent; state.VisorOriginalParentCaptured = true; } } private static void CaptureCameraBase(LocalBodyState state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)state.GameplayCamera == (Object)null) && !state.CameraBaseCaptured && !state.CameraOffsetApplied) { state.CameraBaseLocalPosition = ((Component)state.GameplayCamera).transform.localPosition; state.CameraBaseCaptured = true; } } private static Transform? FindHeadBone(Transform modelRoot, PlayerControllerB player) { SkinnedMeshRenderer thisPlayerModel = player.thisPlayerModel; if ((Object)(object)thisPlayerModel != (Object)null) { Transform[] bones = thisPlayerModel.bones; foreach (Transform val in bones) { if ((Object)(object)val != (Object)null && NameContains(((Object)val).name, "spine.004")) { return val; } } } return FindFirstByNameContains(modelRoot, "spine.004") ?? FindFirstByNameContains(modelRoot, "head"); } private static Transform? FindBodyBone(PlayerControllerB player, string boneName) { SkinnedMeshRenderer thisPlayerModel = player.thisPlayerModel; if ((Object)(object)thisPlayerModel == (Object)null) { return null; } Transform[] bones = thisPlayerModel.bones; foreach (Transform val in bones) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, boneName, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static Transform? FindFirstByNameContains(Transform root, string token) { Queue queue = new Queue(); queue.Enqueue(root); while (queue.Count > 0) { Transform val = queue.Dequeue(); if (NameContains(((Object)val).name, token)) { return val; } for (int i = 0; i < val.childCount; i++) { queue.Enqueue(val.GetChild(i)); } } return null; } private static bool NameContains(string name, string token) { return name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; } private static void EnsureRenderCallbacksHooked() { if (!renderCallbacksHooked) { renderCallbacksHooked = true; RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; RenderPipelineManager.endCameraRendering += OnEndCameraRendering; } } private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { (Action, Action)[] cameraPasses = CameraPasses; for (int i = 0; i < cameraPasses.Length; i++) { (Action, Action) tuple = cameraPasses[i]; tuple.Item1(camera); } } private static void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) { (Action, Action)[] cameraPasses = CameraPasses; for (int i = 0; i < cameraPasses.Length; i++) { (Action, Action) tuple = cameraPasses[i]; tuple.Item2(camera); } } } internal static class ModGUIDs { public const string MoreCompany = "me.swipez.melonloader.morecompany"; public const string TooManyEmotes = "FlipMods.TooManyEmotes"; public const string ImmersiveVisor = "ImmersiveVisor"; } internal static class Players { public static bool IsLocal(PlayerControllerB player) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { return (Object)(object)instance.localPlayerController == (Object)(object)player; } return false; } public static bool IsActivelyHolding(PlayerControllerB player) { GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer != (Object)null && currentlyHeldObjectServer.isHeld && !currentlyHeldObjectServer.isPocketed) { return (Object)(object)currentlyHeldObjectServer.playerHeldBy == (Object)(object)player; } return false; } public static bool IsHoldingTwoHanded(PlayerControllerB player) { return player.twoHanded; } } [BepInPlugin("com.seeya.firstpersonview", "First-Person View", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("com.seeya.firstpersonview"); public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } internal static Harmony Harmony { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; Harmony = _harmony; Log.LogInfo((object)"Initializing First-Person View"); ConfigManager.Initialize(((BaseUnityPlugin)this).Config); MoreCompanyCompat.Initialize(); TooManyEmotesCompat.Initialize(); _harmony.PatchAll(); Log.LogInfo((object)"First-Person View is loaded!"); } } internal static class FirstPersonBody { private static SkinnedMeshRenderer? hideRenderer; private static Mesh? originalMesh; private static Mesh? headlessMesh; private static Mesh? headlessArmlessMesh; private static bool hideArmsInFirstPerson; private static Camera? hideCamera; private static bool hideActive; private static SkinnedMeshRenderer? fpArms; private static bool fpArmsIntended; public static void ApplyBodyRendering(LocalBodyState state, bool showBody, bool useVanillaArms) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 PlayerControllerB player = state.Player; if ((Object)(object)player == (Object)null || !player.isPlayerControlled || player.isPlayerDead) { return; } if (showBody) { if ((Object)(object)player.thisPlayerModel != (Object)null) { if (!((Renderer)player.thisPlayerModel).enabled) { ((Renderer)player.thisPlayerModel).enabled = true; } if ((int)((Renderer)player.thisPlayerModel).shadowCastingMode != 1) { ((Renderer)player.thisPlayerModel).shadowCastingMode = (ShadowCastingMode)1; } } if ((Object)(object)player.thisPlayerModelLOD1 != (Object)null && ((Renderer)player.thisPlayerModelLOD1).enabled) { ((Renderer)player.thisPlayerModelLOD1).enabled = false; } if ((Object)(object)player.thisPlayerModelLOD2 != (Object)null && ((Renderer)player.thisPlayerModelLOD2).enabled) { ((Renderer)player.thisPlayerModelLOD2).enabled = false; } SetFpArmsEnabled(player, useVanillaArms); } else { if ((Object)(object)player.thisPlayerModel != (Object)null && (int)((Renderer)player.thisPlayerModel).shadowCastingMode != 3) { ((Renderer)player.thisPlayerModel).shadowCastingMode = (ShadowCastingMode)3; } SetFpArmsEnabled(player, enabled: true); } } private static void SetFpArmsEnabled(PlayerControllerB player, bool enabled) { fpArms = player.thisPlayerModelArms; fpArmsIntended = enabled; if ((Object)(object)fpArms != (Object)null && ((Renderer)fpArms).enabled != enabled) { ((Renderer)fpArms).enabled = enabled; } } public static void ApplyFirstPersonCameraLayer(LocalBodyState state, bool showBody) { Camera gameplayCamera = state.GameplayCamera; if (!((Object)(object)gameplayCamera == (Object)null)) { int num = 8388608; bool flag = (gameplayCamera.cullingMask & num) != 0; if (showBody && !flag) { gameplayCamera.cullingMask |= num; } else if (!showBody && flag) { gameplayCamera.cullingMask &= ~num; } } } public static void HideHead(LocalBodyState state, bool hideArms) { hideArmsInFirstPerson = hideArms; state.HeadHidden = true; SkinnedMeshRenderer bodyRenderer = state.BodyRenderer; Mesh originalBodyMesh = state.OriginalBodyMesh; if ((Object)(object)bodyRenderer == (Object)null || (Object)(object)originalBodyMesh == (Object)null || (Object)(object)state.HeadBone == (Object)null) { hideActive = false; UpdateShadowProxy(state, active: false); return; } Mesh orCreateHeadlessMesh = MeshSurgery.GetOrCreateHeadlessMesh(originalBodyMesh, bodyRenderer, state.HeadBone); if ((Object)(object)orCreateHeadlessMesh == (Object)null) { hideActive = false; UpdateShadowProxy(state, active: false); return; } if ((Object)(object)bodyRenderer.sharedMesh != (Object)(object)originalBodyMesh) { bodyRenderer.sharedMesh = originalBodyMesh; } headlessArmlessMesh = (hideArms ? MeshSurgery.GetOrCreateHeadlessArmlessMesh(originalBodyMesh, bodyRenderer, state.HeadBone, state.LeftArmBone, state.RightArmBone) : null); hideRenderer = bodyRenderer; originalMesh = originalBodyMesh; headlessMesh = orCreateHeadlessMesh; hideCamera = state.GameplayCamera; hideActive = true; UpdateShadowProxy(state, active: true); } public static void RestoreHead(LocalBodyState state) { hideActive = false; SkinnedMeshRenderer bodyRenderer = state.BodyRenderer; if ((Object)(object)bodyRenderer != (Object)null && (Object)(object)state.OriginalBodyMesh != (Object)null && (Object)(object)bodyRenderer.sharedMesh != (Object)(object)state.OriginalBodyMesh) { bodyRenderer.sharedMesh = state.OriginalBodyMesh; } UpdateShadowProxy(state, active: false); state.HeadHidden = false; } private static void UpdateShadowProxy(LocalBodyState state, bool active) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (!active) { if ((Object)(object)state.ShadowProxy != (Object)null) { ((Renderer)state.ShadowProxy).enabled = false; } return; } SkinnedMeshRenderer bodyRenderer = state.BodyRenderer; Mesh originalBodyMesh = state.OriginalBodyMesh; if ((Object)(object)bodyRenderer == (Object)null || (Object)(object)originalBodyMesh == (Object)null) { return; } if ((Object)(object)state.ShadowProxy == (Object)null) { try { GameObject val = new GameObject("FPVHeadShadowProxy"); val.transform.SetParent(((Component)bodyRenderer).transform.parent, false); val.transform.localPosition = ((Component)bodyRenderer).transform.localPosition; val.transform.localRotation = ((Component)bodyRenderer).transform.localRotation; val.transform.localScale = ((Component)bodyRenderer).transform.localScale; SkinnedMeshRenderer val2 = val.AddComponent(); val2.sharedMesh = originalBodyMesh; val2.bones = bodyRenderer.bones; val2.rootBone = bodyRenderer.rootBone; ((Renderer)val2).sharedMaterials = ((Renderer)bodyRenderer).sharedMaterials; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)3; val2.updateWhenOffscreen = true; state.ShadowProxy = val2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to create head shadow proxy. " + ex.Message)); return; } } ((Component)state.ShadowProxy).gameObject.layer = ((Component)bodyRenderer).gameObject.layer; if (!((Renderer)state.ShadowProxy).enabled) { ((Renderer)state.ShadowProxy).enabled = true; } } public static void ApplyForCamera(Camera camera) { SkinnedMeshRenderer val = hideRenderer; if (!hideActive || (Object)(object)val == (Object)null) { return; } if ((Object)(object)camera == (Object)(object)hideCamera) { Mesh val2 = ((hideArmsInFirstPerson && (Object)(object)headlessArmlessMesh != (Object)null) ? headlessArmlessMesh : headlessMesh); if ((Object)(object)val2 != (Object)null && (Object)(object)val.sharedMesh != (Object)(object)val2) { val.sharedMesh = val2; } } else if ((Object)(object)originalMesh != (Object)null && (Object)(object)val.sharedMesh != (Object)(object)originalMesh) { val.sharedMesh = originalMesh; } if ((Object)(object)fpArms != (Object)null) { ((Renderer)fpArms).enabled = fpArmsIntended && (Object)(object)camera == (Object)(object)hideCamera; } } public static void RestoreAfterCamera(Camera camera) { if ((Object)(object)fpArms != (Object)null && ((Renderer)fpArms).enabled != fpArmsIntended) { ((Renderer)fpArms).enabled = fpArmsIntended; } SkinnedMeshRenderer val = hideRenderer; if (!((Object)(object)val == (Object)null) && !((Object)(object)originalMesh == (Object)null) && (Object)(object)camera == (Object)(object)hideCamera && (Object)(object)val.sharedMesh != (Object)(object)originalMesh) { val.sharedMesh = originalMesh; } } public static void Reset() { hideActive = false; hideRenderer = null; originalMesh = null; headlessMesh = null; headlessArmlessMesh = null; hideArmsInFirstPerson = false; hideCamera = null; fpArms = null; fpArmsIntended = false; } } internal static class HeldItemView { private const int CoverageGridSize = 16; private static readonly int[] coverageRowMin = new int[16]; private static readonly int[] coverageRowMax = new int[16]; private static GrabbableObject? trackedItem; private static Renderer[] renderers = Array.Empty(); private static MotionVectorGenerationMode[] originalMotionModes = Array.Empty(); private static Material[] materials = Array.Empty(); private static Renderer? boundsSource; private static Vector3[] localVertices = Array.Empty(); private static Camera? camera; private static bool hideActive; private static float fadeCurrent = 1f; private static bool fpItemActive; private static Transform? localHolder; private static Transform? serverHolder; private static Transform? itemTransform; private static bool itemRepositioned; private static Vector3 cachedItemPos; private static Quaternion cachedItemRot; public static void ApplyHolder(LocalBodyState state, PlayerControllerB player, bool showBody, bool useVanillaArms) { GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; bool flag = Players.IsActivelyHolding(player); bool isInspectingItem = player.IsInspectingItem; if (flag && (Object)(object)currentlyHeldObjectServer != (Object)null) { Transform val = ((useVanillaArms || isInspectingItem || !showBody) ? player.localItemHolder : player.serverItemHolder); if ((Object)(object)val != (Object)null && (Object)(object)currentlyHeldObjectServer.parentObject != (Object)(object)val) { currentlyHeldObjectServer.parentObject = val; } } bool flag2 = DitherEnabled(); GrabbableObject val2 = (flag ? currentlyHeldObjectServer : null); if ((Object)(object)val2 != (Object)(object)trackedItem) { ResetEffect(); RestoreMotionVectors(); trackedItem = val2; renderers = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponentsInChildren() : Array.Empty()); SuppressMotionVectors(); materials = (Material[])(flag2 ? ((Array)MaterialDither.CollectInstancedMaterials(renderers)) : ((Array)Array.Empty())); boundsSource = ResolveBoundsSource(val2, renderers); localVertices = ResolveLocalVertices(boundsSource); } else if (flag2 && materials.Length == 0 && renderers.Length != 0) { materials = MaterialDither.CollectInstancedMaterials(renderers); } camera = state.GameplayCamera; hideActive = showBody && (Object)(object)val2 != (Object)null && !isInspectingItem; bool flag3 = (fpItemActive = useVanillaArms && showBody && flag && !isInspectingItem && (Object)(object)currentlyHeldObjectServer != (Object)null); localHolder = player.localItemHolder; serverHolder = player.serverItemHolder; itemTransform = (flag3 ? ((Component)currentlyHeldObjectServer).transform : null); } public static void ApplyForCamera(Camera renderingCamera) { RepositionForCamera(renderingCamera); if (hideActive && renderers.Length != 0 && DitherEnabled()) { float fade = (((Object)(object)renderingCamera == (Object)(object)camera) ? ComputeFade(renderingCamera) : 1f); ApplyFade(fade); } } private static void RepositionForCamera(Camera renderingCamera) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) //IL_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (fpItemActive && !itemRepositioned && !((Object)(object)itemTransform == (Object)null) && !((Object)(object)localHolder == (Object)null) && !((Object)(object)serverHolder == (Object)null) && !((Object)(object)renderingCamera == (Object)(object)camera)) { cachedItemPos = itemTransform.position; cachedItemRot = itemTransform.rotation; Vector3 val = localHolder.InverseTransformPoint(cachedItemPos); Quaternion val2 = Quaternion.Inverse(localHolder.rotation) * cachedItemRot; itemTransform.position = serverHolder.TransformPoint(val); itemTransform.rotation = serverHolder.rotation * val2; itemRepositioned = true; } } private static bool DitherEnabled() { if (ConfigManager.HeldItemFadeStyle.Value == HeldItemFadeMode.Off) { return false; } ItemDitherMode value = ConfigManager.ItemDither.Value; if (ConfigManager.Hands.Value != HandsMode.Vanilla) { return (value & ItemDitherMode.ThirdPerson) != 0; } return (value & ItemDitherMode.Vanilla) != 0; } public static void RestoreAfterCamera(Camera renderingCamera) { //IL_0019: 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) if (itemRepositioned && (Object)(object)itemTransform != (Object)null) { itemTransform.position = cachedItemPos; itemTransform.rotation = cachedItemRot; } itemRepositioned = false; if (renderers.Length != 0 && (Object)(object)renderingCamera == (Object)(object)camera) { ApplyFade(1f); } } private static float ComputeFade(Camera renderingCamera) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Renderer val = boundsSource; if ((Object)(object)val == (Object)null) { return 1f; } Vector3[] array = localVertices; Vector3 position = ((Component)renderingCamera).transform.position; float num; if (array.Length == 0) { num = MaterialDither.ProximityFade(NearestBoxDistance(val, position)); } else { Matrix4x4 localToWorldMatrix = val.localToWorldMatrix; float num2 = float.MaxValue; for (int i = 0; i < 16; i++) { coverageRowMin[i] = 16; coverageRowMax[i] = -1; } Vector3[] array2 = array; foreach (Vector3 val2 in array2) { Vector3 val3 = ((Matrix4x4)(ref localToWorldMatrix)).MultiplyPoint3x4(val2); Vector3 val4 = val3 - position; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude < num2) { num2 = sqrMagnitude; } Vector3 val5 = renderingCamera.WorldToViewportPoint(val3); if (!(val5.z <= 0f)) { int num3 = Mathf.Clamp((int)(Mathf.Clamp01(val5.x) * 16f), 0, 15); int num4 = Mathf.Clamp((int)(Mathf.Clamp01(val5.y) * 16f), 0, 15); if (num3 < coverageRowMin[num4]) { coverageRowMin[num4] = num3; } if (num3 > coverageRowMax[num4]) { coverageRowMax[num4] = num3; } } } int num5 = 0; for (int k = 0; k < 16; k++) { if (coverageRowMax[k] >= coverageRowMin[k]) { num5 += coverageRowMax[k] - coverageRowMin[k] + 1; } } float coverage = (float)num5 / 256f; num = Mathf.Min(MaterialDither.ProximityFade(Mathf.Sqrt(num2)), CoverageFade(coverage)); } num = Mathf.Max(0.11f, num); fadeCurrent = MaterialDither.Smooth(fadeCurrent, num, 0.08f); return fadeCurrent; } private static float CoverageFade(float coverage) { return 1f - Mathf.Clamp01(Mathf.InverseLerp(0.45f, 0.6f, coverage)); } private static float NearestBoxDistance(Renderer renderer, Vector3 worldPoint) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0020: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Matrix4x4 val = renderer.worldToLocalMatrix; Vector3 val2 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(worldPoint); Bounds localBounds = renderer.localBounds; Vector3 val3 = ((Bounds)(ref localBounds)).ClosestPoint(val2); val = renderer.localToWorldMatrix; Vector3 val4 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(val3); return Vector3.Distance(worldPoint, val4); } private static Vector3[] ResolveLocalVertices(Renderer? source) { SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null); Mesh val2; if (val == null) { if (source == null) { val2 = null; } else { MeshFilter component = ((Component)source).GetComponent(); val2 = ((component != null) ? component.sharedMesh : null); } } else { val2 = val.sharedMesh; } Mesh val3 = val2; if (!((Object)(object)val3 != (Object)null) || !val3.isReadable) { return Array.Empty(); } return val3.vertices; } private static Renderer? ResolveBoundsSource(GrabbableObject? item, Renderer[] itemRenderers) { if ((Object)(object)item == (Object)null) { return null; } if ((Object)(object)item.mainObjectRenderer != (Object)null) { return (Renderer?)(object)item.mainObjectRenderer; } foreach (Renderer val in itemRenderers) { if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void ApplyFade(float fade) { MaterialDither.Set(renderers, materials, fade); } private static void ResetEffect() { MaterialDither.Set(renderers, materials, 1f); fadeCurrent = 1f; } private static void SuppressMotionVectors() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected I4, but got Unknown originalMotionModes = (MotionVectorGenerationMode[])((renderers.Length != 0) ? ((Array)new MotionVectorGenerationMode[renderers.Length]) : ((Array)Array.Empty())); for (int i = 0; i < renderers.Length; i++) { Renderer val = renderers[i]; if (!((Object)(object)val == (Object)null)) { originalMotionModes[i] = (MotionVectorGenerationMode)(int)val.motionVectorGenerationMode; val.motionVectorGenerationMode = (MotionVectorGenerationMode)2; } } } private static void RestoreMotionVectors() { for (int i = 0; i < renderers.Length && i < originalMotionModes.Length; i++) { Renderer val = renderers[i]; if ((Object)(object)val != (Object)null) { val.motionVectorGenerationMode = originalMotionModes[i]; } } originalMotionModes = Array.Empty(); } public static void Reset() { ResetEffect(); RestoreMotionVectors(); trackedItem = null; renderers = Array.Empty(); materials = Array.Empty(); boundsSource = null; localVertices = Array.Empty(); camera = null; hideActive = false; fpItemActive = false; localHolder = null; serverHolder = null; itemTransform = null; itemRepositioned = false; } } internal static class MaterialDither { public const string CrossfadeKeyword = "LOD_FADE_CROSSFADE"; public static readonly int LodFadeId = Shader.PropertyToID("unity_LODFade"); private static MaterialPropertyBlock? scratch; public static Material[] CollectInstancedMaterials(params Renderer[] renderers) { if (renderers.Length == 0) { return Array.Empty(); } List list = new List(); foreach (Renderer val in renderers) { if ((Object)(object)val == (Object)null) { continue; } Material[] materials = val.materials; foreach (Material val2 in materials) { if ((Object)(object)val2 != (Object)null) { list.Add(val2); } } } return list.ToArray(); } public static void Set(Renderer[] renderers, Material[] materials, float fade) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) ToggleKeyword(materials, fade < 0.999f); Vector4 lodFade = default(Vector4); ((Vector4)(ref lodFade))..ctor(fade, fade, 0f, 0f); foreach (Renderer renderer in renderers) { WriteFade(renderer, lodFade); } } public static void Set(Renderer? renderer, Material[] materials, float fade) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) ToggleKeyword(materials, fade < 0.999f); WriteFade(renderer, new Vector4(fade, fade, 0f, 0f)); } private static void ToggleKeyword(Material[] materials, bool enable) { foreach (Material val in materials) { if (!((Object)(object)val == (Object)null)) { if (enable) { val.EnableKeyword("LOD_FADE_CROSSFADE"); } else { val.DisableKeyword("LOD_FADE_CROSSFADE"); } } } } private static void WriteFade(Renderer? renderer, Vector4 lodFade) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (!((Object)(object)renderer == (Object)null)) { if (scratch == null) { scratch = new MaterialPropertyBlock(); } renderer.GetPropertyBlock(scratch); scratch.SetVector(LodFadeId, lodFade); renderer.SetPropertyBlock(scratch); } } public static float ProximityFade(float distance) { return Mathf.Clamp01(Mathf.InverseLerp(0.1f, 0.35f, distance)); } public static float Smooth(float current, float target, float smoothTime) { float num = 1f - Mathf.Exp((0f - Time.deltaTime) / smoothTime); return Mathf.Lerp(current, target, num); } } internal static class MeshSurgery { private static readonly Dictionary HeadlessMeshCache = new Dictionary(); private static readonly Dictionary HeadlessArmlessMeshCache = new Dictionary(); private static readonly Dictionary ReadableCopies = new Dictionary(); private static readonly HashSet GeneratedMeshIds = new HashSet(); private static readonly HashSet LoggedUnreadableMeshes = new HashSet(); public static bool IsGenerated(int meshInstanceId) { return GeneratedMeshIds.Contains(meshInstanceId); } private static int DominantBoneIndex(BoneWeight bw) { int result = ((BoneWeight)(ref bw)).boneIndex0; float num = ((BoneWeight)(ref bw)).weight0; if (((BoneWeight)(ref bw)).weight1 > num) { num = ((BoneWeight)(ref bw)).weight1; result = ((BoneWeight)(ref bw)).boneIndex1; } if (((BoneWeight)(ref bw)).weight2 > num) { num = ((BoneWeight)(ref bw)).weight2; result = ((BoneWeight)(ref bw)).boneIndex2; } if (((BoneWeight)(ref bw)).weight3 > num) { num = ((BoneWeight)(ref bw)).weight3; result = ((BoneWeight)(ref bw)).boneIndex3; } if (!(num > 0f)) { return -1; } return result; } private static bool[]? BuildPipeMask(Mesh mesh, SkinnedMeshRenderer skinned, Transform headBone) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Transform parent = headBone.parent; Transform[] bones = skinned.bones; if ((Object)(object)parent == (Object)null || mesh.bindposes == null || mesh.bindposes.Length < bones.Length) { return null; } int num = Array.IndexOf(bones, parent); int num2 = Array.IndexOf(bones, headBone); if (num < 0 || num2 < 0) { return null; } if (!TryGetBodyForward(mesh, bones, num2, num, out var forward)) { return null; } Vector3 val = BoneBindPosition(mesh, num); BoneWeight[] boneWeights = mesh.boneWeights; Vector3[] vertices = mesh.vertices; bool[] array = new bool[vertices.Length]; int num3 = 0; for (int i = 0; i < vertices.Length; i++) { if (DominantBoneIndex(boneWeights[i]) == num && Vector3.Dot(vertices[i] - val, forward) < 0f) { array[i] = true; num3++; } } if (num3 <= 0) { return null; } return array; } private static bool TryGetBodyForward(Mesh mesh, Transform[] bones, int headIndex, int neckIndex, out Vector3 forward) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) forward = Vector3.zero; int num = FindBoneIndex(bones, "toe.L"); int num2 = FindBoneIndex(bones, "heel.02.L"); int num3 = FindBoneIndex(bones, "toe.R"); int num4 = FindBoneIndex(bones, "heel.02.R"); if (num < 0 || num2 < 0 || num3 < 0 || num4 < 0) { return false; } Vector3 val = BoneBindPosition(mesh, num) - BoneBindPosition(mesh, num2) + (BoneBindPosition(mesh, num3) - BoneBindPosition(mesh, num4)); Vector3 val2 = BoneBindPosition(mesh, headIndex) - BoneBindPosition(mesh, neckIndex); if (((Vector3)(ref val2)).sqrMagnitude > 1E-06f) { val -= ((Vector3)(ref val2)).normalized * Vector3.Dot(val, ((Vector3)(ref val2)).normalized); } if (((Vector3)(ref val)).sqrMagnitude < 1E-06f) { return false; } forward = ((Vector3)(ref val)).normalized; return true; } private static Vector3 BoneBindPosition(Mesh mesh, int boneIndex) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Matrix4x4 inverse = ((Matrix4x4)(ref mesh.bindposes[boneIndex])).inverse; return new Vector3(inverse.m03, inverse.m13, inverse.m23); } private static int FindBoneIndex(Transform[] bones, string boneName) { for (int i = 0; i < bones.Length; i++) { if ((Object)(object)bones[i] != (Object)null && string.Equals(((Object)bones[i]).name, boneName, StringComparison.OrdinalIgnoreCase)) { return i; } } return -1; } public static void ClearCaches() { foreach (Mesh value in HeadlessMeshCache.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } foreach (Mesh value2 in HeadlessArmlessMeshCache.Values) { if ((Object)(object)value2 != (Object)null) { Object.Destroy((Object)(object)value2); } } foreach (Mesh value3 in ReadableCopies.Values) { if ((Object)(object)value3 != (Object)null) { Object.Destroy((Object)(object)value3); } } HeadlessMeshCache.Clear(); HeadlessArmlessMeshCache.Clear(); ReadableCopies.Clear(); GeneratedMeshIds.Clear(); LoggedUnreadableMeshes.Clear(); } public static Mesh? GetOrCreateHeadlessMesh(Mesh sourceMesh, SkinnedMeshRenderer skinned, Transform headBone) { int instanceID = ((Object)sourceMesh).GetInstanceID(); if (HeadlessMeshCache.TryGetValue(instanceID, out Mesh value) && (Object)(object)value != (Object)null) { return value; } Mesh val = ResolveReadable(sourceMesh, instanceID); if ((Object)(object)val == (Object)null) { return null; } bool[] pipeMask = BuildPipeMask(val, skinned, headBone); Mesh val2 = TryBuildFilteredMesh(val, GetHeadBoneIndices(skinned, headBone), pipeMask, "_FPVHeadless"); if ((Object)(object)val2 != (Object)null) { HeadlessMeshCache[instanceID] = val2; GeneratedMeshIds.Add(((Object)val2).GetInstanceID()); } return val2; } public static Mesh? GetOrCreateHeadlessArmlessMesh(Mesh sourceMesh, SkinnedMeshRenderer skinned, Transform headBone, Transform? leftArm, Transform? rightArm) { int instanceID = ((Object)sourceMesh).GetInstanceID(); if (HeadlessArmlessMeshCache.TryGetValue(instanceID, out Mesh value) && (Object)(object)value != (Object)null) { return value; } Mesh val = ResolveReadable(sourceMesh, instanceID); if ((Object)(object)val == (Object)null) { return null; } Mesh val2; try { val2 = BuildHeadlessArmlessMesh(val, skinned, headBone, leftArm, rightArm, "_FPVHeadlessArmless"); } catch (Exception) { return null; } if ((Object)(object)val2 != (Object)null) { HeadlessArmlessMeshCache[instanceID] = val2; GeneratedMeshIds.Add(((Object)val2).GetInstanceID()); } return val2; } private static Mesh? BuildHeadlessArmlessMesh(Mesh sourceMesh, SkinnedMeshRenderer skinned, Transform headBone, Transform? leftArm, Transform? rightArm, string nameSuffix) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) BoneWeight[] boneWeights = sourceMesh.boneWeights; if (boneWeights == null || boneWeights.Length == 0) { return null; } HashSet headBoneIndices = GetHeadBoneIndices(skinned, headBone); HashSet armBoneIndices = GetArmBoneIndices(skinned, leftArm, rightArm); if (headBoneIndices.Count == 0 && armBoneIndices.Count == 0) { return null; } bool[] array = BuildPipeMask(sourceMesh, skinned, headBone); int num = boneWeights.Length; float[] array2 = new float[num]; bool[] array3 = new bool[num]; bool[] array4 = new bool[num]; for (int i = 0; i < num; i++) { BoneWeight bw = boneWeights[i]; array2[i] = InfluenceOf(bw, headBoneIndices); array3[i] = IsDominatedBy(bw, headBoneIndices) || (array != null && array[i]); array4[i] = IsDominatedBy(bw, armBoneIndices); } List list = CollectSeamVertices(sourceMesh, array2, array3, array4); if (list.Count == 0) { return null; } Vector3[] vertices = sourceMesh.vertices; Vector3[] array5 = (Vector3[])vertices.Clone(); BoneWeight[] array6 = (BoneWeight[])boneWeights.Clone(); for (int j = 0; j < num; j++) { if (array4[j]) { int num2 = NearestVertex(vertices[j], list, vertices); array5[j] = vertices[num2]; array6[j] = boneWeights[num2]; } } Mesh val = Object.Instantiate(sourceMesh); ((Object)val).name = ((Object)sourceMesh).name + nameSuffix; val.vertices = array5; val.boneWeights = array6; for (int k = 0; k < val.subMeshCount; k++) { int[] triangles = sourceMesh.GetTriangles(k); List list2 = new List(triangles.Length); for (int l = 0; l < triangles.Length; l += 3) { int num3 = triangles[l]; int num4 = triangles[l + 1]; int num5 = triangles[l + 2]; if (!ShouldCullTriangle(num3, num4, num5, array2, array3) && (!array4[num3] || !array4[num4] || !array4[num5])) { list2.Add(num3); list2.Add(num4); list2.Add(num5); } } val.SetTriangles(list2, k); } val.RecalculateBounds(); return val; } private static List CollectSeamVertices(Mesh mesh, float[] headInfluence, bool[] headDominant, bool[] armDominant) { HashSet hashSet = new HashSet(); for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = mesh.GetTriangles(i); for (int j = 0; j < triangles.Length; j += 3) { int num = triangles[j]; int num2 = triangles[j + 1]; int num3 = triangles[j + 2]; if (!ShouldCullTriangle(num, num2, num3, headInfluence, headDominant) && (armDominant[num] || armDominant[num2] || armDominant[num3])) { if (!armDominant[num]) { hashSet.Add(num); } if (!armDominant[num2]) { hashSet.Add(num2); } if (!armDominant[num3]) { hashSet.Add(num3); } } } } return new List(hashSet); } private static int NearestVertex(Vector3 point, List candidates, Vector3[] vertices) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) int result = candidates[0]; float num = float.MaxValue; foreach (int candidate in candidates) { Vector3 val = vertices[candidate] - point; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = candidate; } } return result; } private static Mesh? TryBuildFilteredMesh(Mesh sourceMesh, HashSet removalBoneIndices, bool[]? pipeMask, string nameSuffix) { try { return BuildMeshWithoutBones(sourceMesh, removalBoneIndices, pipeMask, nameSuffix); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to build '" + ((Object)sourceMesh).name + nameSuffix + "'. " + ex.Message)); return null; } } private static Mesh? BuildMeshWithoutBones(Mesh sourceMesh, HashSet removalBoneIndices, bool[]? pipeMask, string nameSuffix) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_004a: Unknown result type (might be due to invalid IL or missing references) BoneWeight[] boneWeights = sourceMesh.boneWeights; if (boneWeights == null || boneWeights.Length == 0) { return null; } if (removalBoneIndices.Count == 0) { return null; } float[] array = new float[boneWeights.Length]; bool[] array2 = new bool[boneWeights.Length]; for (int i = 0; i < boneWeights.Length; i++) { BoneWeight bw = boneWeights[i]; array[i] = InfluenceOf(bw, removalBoneIndices); array2[i] = IsDominatedBy(bw, removalBoneIndices) || (pipeMask != null && pipeMask[i]); } Mesh val = Object.Instantiate(sourceMesh); ((Object)val).name = ((Object)sourceMesh).name + nameSuffix; for (int j = 0; j < val.subMeshCount; j++) { int[] triangles = sourceMesh.GetTriangles(j); List list = new List(triangles.Length); for (int k = 0; k < triangles.Length; k += 3) { int num = triangles[k]; int num2 = triangles[k + 1]; int num3 = triangles[k + 2]; if (!ShouldCullTriangle(num, num2, num3, array, array2)) { list.Add(num); list.Add(num2); list.Add(num3); } } val.SetTriangles(list, j); } val.RecalculateBounds(); return val; } private static float InfluenceOf(BoneWeight bw, HashSet set) { float num = 0f; if (set.Contains(((BoneWeight)(ref bw)).boneIndex0)) { num += ((BoneWeight)(ref bw)).weight0; } if (set.Contains(((BoneWeight)(ref bw)).boneIndex1)) { num += ((BoneWeight)(ref bw)).weight1; } if (set.Contains(((BoneWeight)(ref bw)).boneIndex2)) { num += ((BoneWeight)(ref bw)).weight2; } if (set.Contains(((BoneWeight)(ref bw)).boneIndex3)) { num += ((BoneWeight)(ref bw)).weight3; } return num; } private static bool IsDominatedBy(BoneWeight bw, HashSet set) { int item = ((BoneWeight)(ref bw)).boneIndex0; float num = ((BoneWeight)(ref bw)).weight0; if (((BoneWeight)(ref bw)).weight1 > num) { num = ((BoneWeight)(ref bw)).weight1; item = ((BoneWeight)(ref bw)).boneIndex1; } if (((BoneWeight)(ref bw)).weight2 > num) { num = ((BoneWeight)(ref bw)).weight2; item = ((BoneWeight)(ref bw)).boneIndex2; } if (((BoneWeight)(ref bw)).weight3 > num) { num = ((BoneWeight)(ref bw)).weight3; item = ((BoneWeight)(ref bw)).boneIndex3; } if (num > 0f) { return set.Contains(item); } return false; } private static HashSet GetHeadBoneIndices(SkinnedMeshRenderer skinned, Transform headBone) { HashSet hashSet = new HashSet(); Transform[] bones = skinned.bones; for (int i = 0; i < bones.Length; i++) { Transform val = bones[i]; if (!((Object)(object)val == (Object)null) && ((Object)(object)val == (Object)(object)headBone || val.IsChildOf(headBone) || ContainsHeadHint(((Object)val).name))) { hashSet.Add(i); } } return hashSet; } private static HashSet GetArmBoneIndices(SkinnedMeshRenderer skinned, Transform? leftArm, Transform? rightArm) { HashSet hashSet = new HashSet(); Transform[] bones = skinned.bones; for (int i = 0; i < bones.Length; i++) { Transform val = bones[i]; if (!((Object)(object)val == (Object)null)) { bool flag = (Object)(object)leftArm != (Object)null && ((Object)(object)val == (Object)(object)leftArm || val.IsChildOf(leftArm)); bool flag2 = (Object)(object)rightArm != (Object)null && ((Object)(object)val == (Object)(object)rightArm || val.IsChildOf(rightArm)); if (flag || flag2) { hashSet.Add(i); } } } return hashSet; } private static bool ShouldCullTriangle(int a, int b, int c, float[] headInfluence, bool[] dominantHead) { float num = ((a >= 0 && a < headInfluence.Length) ? headInfluence[a] : 0f); float num2 = ((b >= 0 && b < headInfluence.Length) ? headInfluence[b] : 0f); float num3 = ((c >= 0 && c < headInfluence.Length) ? headInfluence[c] : 0f); int num4 = 0; if (num >= 0.35f) { num4++; } if (num2 >= 0.35f) { num4++; } if (num3 >= 0.35f) { num4++; } int num5 = 0; if (a >= 0 && a < dominantHead.Length && dominantHead[a]) { num5++; } if (b >= 0 && b < dominantHead.Length && dominantHead[b]) { num5++; } if (c >= 0 && c < dominantHead.Length && dominantHead[c]) { num5++; } if (num5 >= 2 || num4 >= 2) { return true; } float num6 = (num + num2 + num3) / 3f; if (num5 >= 1) { return num6 >= 0.3f; } return false; } private static bool ContainsHeadHint(string? value) { if (string.IsNullOrWhiteSpace(value)) { return false; } string[] headBoneNameHints = Constants.HeadBoneNameHints; foreach (string value2 in headBoneNameHints) { if (value.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static Mesh? ResolveReadable(Mesh sourceMesh, int meshId) { if (sourceMesh.isReadable) { return sourceMesh; } if (ReadableCopies.TryGetValue(meshId, out Mesh value)) { return value; } Mesh val = null; try { Mesh val2 = MakeReadableMeshCopy(sourceMesh); if (val2.boneWeights.Length != 0 && val2.bindposes.Length != 0) { val = val2; } else { Object.Destroy((Object)(object)val2); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Mesh '" + ((Object)sourceMesh).name + "' could not be copied from the GPU. " + ex.Message)); } if ((Object)(object)val == (Object)null && LoggedUnreadableMeshes.Add(meshId)) { Plugin.Log.LogWarning((object)("Mesh '" + ((Object)sourceMesh).name + "' is not readable; the head can't be hidden on this model.")); } ReadableCopies[meshId] = val; return val; } private static Mesh MakeReadableMeshCopy(Mesh nonReadableMesh) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh { name = ((Object)nonReadableMesh).name, indexFormat = nonReadableMesh.indexFormat }; nonReadableMesh.vertexBufferTarget = (Target)1; if (nonReadableMesh.vertexBufferCount > 0) { GraphicsBuffer vertexBuffer = nonReadableMesh.GetVertexBuffer(0); try { int num = vertexBuffer.stride * vertexBuffer.count; byte[] array = new byte[num]; vertexBuffer.GetData((Array)array); val.SetVertexBufferParams(nonReadableMesh.vertexCount, nonReadableMesh.GetVertexAttributes()); val.SetVertexBufferData(array, 0, 0, num, 0, (MeshUpdateFlags)0); } finally { ((IDisposable)vertexBuffer)?.Dispose(); } } nonReadableMesh.indexBufferTarget = (Target)2; val.subMeshCount = nonReadableMesh.subMeshCount; GraphicsBuffer indexBuffer = nonReadableMesh.GetIndexBuffer(); try { int num2 = indexBuffer.stride * indexBuffer.count; byte[] array2 = new byte[num2]; indexBuffer.GetData((Array)array2); val.SetIndexBufferParams(indexBuffer.count, nonReadableMesh.indexFormat); val.SetIndexBufferData(array2, 0, 0, num2, (MeshUpdateFlags)0); } finally { ((IDisposable)indexBuffer)?.Dispose(); } int num3 = 0; for (int i = 0; i < val.subMeshCount; i++) { int indexCount = (int)nonReadableMesh.GetIndexCount(i); val.SetSubMesh(i, new SubMeshDescriptor(num3, indexCount, (MeshTopology)0), (MeshUpdateFlags)0); num3 += indexCount; } val.bindposes = nonReadableMesh.bindposes; val.RecalculateBounds(); return val; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.seeya.firstpersonview"; public const string PLUGIN_NAME = "First-Person View"; public const string PLUGIN_VERSION = "1.0.1"; } } namespace FirstPersonView.Patches { [HarmonyPatch(typeof(PlayerControllerB))] internal static class LocalBodyViewPatches { private static readonly HashSet _loggedTickErrors = new HashSet(); [HarmonyPatch("ConnectClientToPlayerObject")] [HarmonyPostfix] private static void ConnectClientToPlayerObject_Postfix(PlayerControllerB __instance) { if ((Object)(object)StartOfRound.Instance?.localPlayerController == (Object)(object)__instance) { VehicleCompat.EnsurePatched(); LocalBodyViewController.ResetAllStates(); } } [HarmonyPatch("LateUpdate")] [HarmonyPostfix] [HarmonyPriority(0)] private static void LateUpdate_Postfix(PlayerControllerB __instance) { try { LocalBodyViewController.Tick(__instance); } catch (Exception ex) { if (_loggedTickErrors.Add($"{ex.GetType()}: {ex.Message}")) { Plugin.Log.LogError((object)$"Local body update failed.\n{ex}"); } } } [HarmonyPatch("SetHoverTipAndCurrentInteractTrigger")] [HarmonyPrefix] private static void SetHoverTipAndCurrentInteractTrigger_Prefix(PlayerControllerB __instance) { LocalBodyViewController.AlignCameraForInteractionRay(__instance); } } } namespace FirstPersonView.Compat { internal static class MoreCompanyCompat { private static bool _initialized; private static bool _isInstalled; private static Type? _cosmeticApplicationType; private static Type? _cosmeticInstanceType; private static FieldInfo? _spawnedCosmeticsField; private static FieldInfo? _cosmeticTypeField; public static void Initialize() { if (!_initialized) { _initialized = true; _isInstalled = Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany"); if (_isInstalled) { Plugin.Log.LogInfo((object)"MoreCompany detected."); } } } public static void ApplyLocalCosmeticVisibility(PlayerControllerB player, bool localBodyVisible, bool firstPersonArmsActive) { if (!_isInstalled || !ConfigManager.EnableMoreCompanyCompatibility.Value || !localBodyVisible || !TryResolveSpawnedCosmetics(player, out IEnumerable cosmetics)) { return; } foreach (object item in cosmetics) { Component val = (Component)((item is Component) ? item : null); if (val != null) { bool flag = ShouldShowCosmetic(item, firstPersonArmsActive); if (val.gameObject.activeSelf != flag) { val.gameObject.SetActive(flag); } } } } private static bool TryResolveSpawnedCosmetics(PlayerControllerB player, out IEnumerable cosmetics) { cosmetics = Array.Empty(); if (!TryResolveTypes()) { return false; } if (_cosmeticApplicationType == null || _spawnedCosmeticsField == null) { return false; } Transform obj = ((Component)player).transform.Find("ScavengerModel"); Transform val = ((obj != null) ? obj.Find("metarig") : null); if ((Object)(object)val == (Object)null) { return false; } Component component = ((Component)val).GetComponent(_cosmeticApplicationType); if ((Object)(object)component == (Object)null) { return false; } object value = _spawnedCosmeticsField.GetValue(component); if (!(value is IEnumerable enumerable)) { return false; } cosmetics = enumerable; return true; } private static bool ShouldShowCosmetic(object cosmetic, bool firstPersonArmsActive) { if (_cosmeticTypeField == null) { return true; } string text = _cosmeticTypeField.GetValue(cosmetic)?.ToString() ?? string.Empty; if (firstPersonArmsActive && text.IndexOf("ARM", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } return text switch { "HAT" => ConfigManager.ShowMoreCompanyHat.Value, "CHEST" => ConfigManager.ShowMoreCompanyChest.Value, "HIP" => ConfigManager.ShowMoreCompanyHip.Value, "R_LOWER_ARM" => ConfigManager.ShowMoreCompanyRightLowerArm.Value, "L_SHIN" => ConfigManager.ShowMoreCompanyLeftShin.Value, "R_SHIN" => ConfigManager.ShowMoreCompanyRightShin.Value, _ => true, }; } private static bool TryResolveTypes() { if (_cosmeticApplicationType != null && _spawnedCosmeticsField != null && _cosmeticInstanceType != null) { return true; } Assembly assembly = Reflection.FindAssembly("MoreCompany"); if (assembly == null) { return false; } _cosmeticApplicationType = assembly.GetType("MoreCompany.Cosmetics.CosmeticApplication"); _cosmeticInstanceType = assembly.GetType("MoreCompany.Cosmetics.CosmeticInstance"); if (_cosmeticApplicationType == null || _cosmeticInstanceType == null) { return false; } _spawnedCosmeticsField = _cosmeticApplicationType.GetField("spawnedCosmetics", BindingFlags.Instance | BindingFlags.Public); _cosmeticTypeField = _cosmeticInstanceType.GetField("cosmeticType", BindingFlags.Instance | BindingFlags.Public); return _spawnedCosmeticsField != null; } } internal static class Reflection { public static Assembly? FindAssembly(string name) { return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == name); } public static IEnumerable GetLoadableTypes(this Assembly assembly) { if (assembly == null) { return Enumerable.Empty(); } try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type type) => type != null); } } } internal static class TooManyEmotesCompat { private static bool _initialized; private static bool _isInstalled; private static PropertyInfo? _firstPersonEmotesEnabledProperty; private static PropertyInfo? _emoteControllerLocalProperty; private static MethodInfo? _isPerformingCustomEmoteMethod; public static void Initialize() { if (!_initialized) { _initialized = true; bool flag = TryResolveTypes(); _isInstalled = flag && ConfigManager.EnableTooManyEmotesCompatibility.Value; if (flag) { Plugin.Log.LogInfo((object)"TooManyEmotes detected."); } } } public static bool IsFirstPersonEmoteActive() { if (!_isInstalled || _firstPersonEmotesEnabledProperty == null || _emoteControllerLocalProperty == null || _isPerformingCustomEmoteMethod == null) { return false; } object value = _firstPersonEmotesEnabledProperty.GetValue(null); if (!(value is bool) || !(bool)value) { return false; } object value2 = _emoteControllerLocalProperty.GetValue(null); if (value2 != null) { value = _isPerformingCustomEmoteMethod.Invoke(value2, null); if (value is bool) { return (bool)value; } return false; } return false; } private static bool TryResolveTypes() { Assembly assembly = Reflection.FindAssembly("TooManyEmotes"); if (assembly == null) { return false; } Type type = assembly.GetType("TooManyEmotes.Patches.ThirdPersonEmoteController"); Type type2 = assembly.GetType("TooManyEmotes.EmoteControllerPlayer"); if (type == null || type2 == null) { return false; } _firstPersonEmotesEnabledProperty = type.GetProperty("firstPersonEmotesEnabled", BindingFlags.Static | BindingFlags.Public); _emoteControllerLocalProperty = type2.GetProperty("emoteControllerLocal", BindingFlags.Static | BindingFlags.Public); _isPerformingCustomEmoteMethod = type2.GetMethod("IsPerformingCustomEmote", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); if (_firstPersonEmotesEnabledProperty != null && _emoteControllerLocalProperty != null) { return _isPerformingCustomEmoteMethod != null; } return false; } } internal static class VehicleCompat { private static bool _patched; private static FieldInfo? _ignitionCoroutineField; public static void EnsurePatched() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (_patched) { return; } _patched = true; HarmonyMethod postfix = new HarmonyMethod(typeof(VehicleCompat), "KeyPostfix", (Type[])null); foreach (Type item in CollectVehicleTypes()) { TryPatch(item, "Update", postfix); TryPatch(item, "LateUpdate", postfix); } } private static void TryPatch(Type type, string methodName, HarmonyMethod postfix) { MethodInfo method = type.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return; } try { Plugin.Harmony.Patch((MethodBase)method, (HarmonyMethod)null, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Vehicle key compat: could not patch " + type.Name + "." + methodName + ". " + ex.Message)); } } private static IEnumerable CollectVehicleTypes() { Type baseType = typeof(VehicleController); yield return baseType; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { foreach (Type loadableType in assembly.GetLoadableTypes()) { if (loadableType != baseType && baseType.IsAssignableFrom(loadableType)) { yield return loadableType; } } } } private static void KeyPostfix(VehicleController __instance) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //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_0093: Unknown result type (might be due to invalid IL or missing references) if (LocalBodyViewController.LocalBodyShown && __instance.keyIsInDriverHand && __instance.localPlayerInControl && !((Object)(object)__instance.keyObject == (Object)null) && !IsIgnitionInProgress(__instance)) { PlayerControllerB currentDriver = __instance.currentDriver; Transform val = (((Object)(object)currentDriver != (Object)null) ? currentDriver.serverItemHolder : null); if (!((Object)(object)val == (Object)null)) { Transform transform = ((Component)__instance.keyObject).transform; transform.rotation = val.rotation * Quaternion.Euler(Constants.CruiserKeyRotationOffset); transform.position = val.position + val.rotation * Constants.CruiserKeyPositionOffset; } } } private static bool IsIgnitionInProgress(VehicleController vehicle) { if ((object)_ignitionCoroutineField == null) { _ignitionCoroutineField = typeof(VehicleController).GetField("keyIgnitionCoroutine", BindingFlags.Instance | BindingFlags.NonPublic); } if (_ignitionCoroutineField != null) { return _ignitionCoroutineField.GetValue(vehicle) != null; } return false; } } }