Decompiled source of DadsFPP v1.1.5

DadsFPP.dll

Decompiled 6 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("DadsFPP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.5.0")]
[assembly: AssemblyInformationalVersion("1.1.5+fd3b16b12d2ac9c63332d4a2d613c5fab24cd9ed")]
[assembly: AssemblyProduct("DadsFPP")]
[assembly: AssemblyTitle("DadsFPP")]
[assembly: AssemblyVersion("1.1.5.0")]
[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 DadsFPP
{
	[BepInPlugin("com.dadisbored.dadsfpp", "DadsFPP", "1.1.5")]
	[BepInProcess("valheim.exe")]
	public sealed class DadsFPPPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.dadisbored.dadsfpp";

		public const string PluginName = "DadsFPP";

		public const string PluginVersion = "1.1.5";

		internal static DadsFPPPlugin? Instance;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> FirstPerson;

		internal static ConfigEntry<KeyboardShortcut> ToggleKey;

		internal static ConfigEntry<float> FieldOfView;

		internal static ConfigEntry<float> ForwardOffset;

		internal static ConfigEntry<float> VerticalOffset;

		internal static ConfigEntry<float> NearClip;

		internal static ConfigEntry<bool> HideHead;

		internal static ConfigEntry<bool> ShowArmsAndWeapons;

		internal static ConfigEntry<Vector3> ArmViewOffset;

		private Harmony? _harmony;

		internal readonly FirstPersonCamera Controller = new FirstPersonCamera();

		internal readonly HealthReadout HealthNumbers = new HealthReadout();

		private void Awake()
		{
			//IL_0060: 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_00ac: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Enable DadsFPP.");
			FirstPerson = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "First Person", true, "Use first person. The toggle updates this setting.");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "Toggle Perspective", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Switch first/third person during gameplay.");
			FieldOfView = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Camera", "Field of View", 65f, new ConfigDescription("First-person vertical FOV. Valheim's default is 65 degrees; slider range is 60–110 degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 110f), Array.Empty<object>()));
			ForwardOffset = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Camera", "Forward Offset", 0.12f, new ConfigDescription("Meters forward from the player's eyes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.1f, 0.3f), Array.Empty<object>()));
			VerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Camera", "Vertical Offset", 0f, new ConfigDescription("Meters above or below the player's eyes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			NearClip = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Camera", "Near Clip", 0.03f, new ConfigDescription("Near clipping plane in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.15f), Array.Empty<object>()));
			HideHead = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Visibility", "Hide Head", true, "Hide your head, hair, beard and helmet for the world camera only. Equipment remains equipped.");
			ShowArmsAndWeapons = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Visibility", "Show Arms and Weapons", true, "Align your animated arms and held weapons with the first-person view during rendering.");
			ArmViewOffset = ((BaseUnityPlugin)this).Config.Bind<Vector3>("3 - Visibility", "Arm View Offset", new Vector3(0f, 0.35f, 0.45f), "Render offset for animated arms and held equipment in meters: X right, Y up, Z forward. Applies only to the first-person camera.");
			Controller.Subscribe();
			_harmony = new Harmony("com.dadisbored.dadsfpp");
			_harmony.PatchAll(typeof(DadsFPPPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"DadsFPP 1.1.5 loaded. F6 toggles perspective by default.");
		}

		private void Update()
		{
			//IL_0026: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			if (!Enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null || !GameplayInputAvailable())
			{
				return;
			}
			KeyboardShortcut value = ToggleKey.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return;
				}
			}
			FirstPerson.Value = !FirstPerson.Value;
			if (!FirstPerson.Value)
			{
				Controller.Restore();
			}
		}

		private void OnGUI()
		{
			HealthNumbers.Draw(Controller);
		}

		internal static bool GameplayInputAvailable()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)Cursor.lockState == 1 && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible())
			{
				if ((Object)(object)Chat.instance != (Object)null)
				{
					return !Chat.instance.HasFocus();
				}
				return true;
			}
			return false;
		}

		private void OnDestroy()
		{
			Controller.Unsubscribe();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateCamera", new Type[] { typeof(float) })]
	internal static class CameraUpdatePatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(GameCamera __instance, Camera ___m_camera, bool ___m_freeFly)
		{
			DadsFPPPlugin.Instance?.Controller.Update(__instance, ___m_camera, Player.m_localPlayer, ___m_freeFly);
		}
	}
	[HarmonyPatch(typeof(Character), "SetVisible", new Type[] { typeof(bool) })]
	internal static class CharacterVisibilityPatch
	{
		private static void Prefix(Character __instance, ref bool __0)
		{
			DadsFPPPlugin? instance = DadsFPPPlugin.Instance;
			if (instance != null && instance.Controller.IsActiveFor(__instance))
			{
				__0 = true;
			}
		}
	}
	internal sealed class FirstPersonCamera
	{
		private readonly struct ArmPose
		{
			internal readonly Vector3 Position;

			internal readonly Quaternion Rotation;

			internal ArmPose(Transform arm)
			{
				//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_000e: 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)
				Position = arm.localPosition;
				Rotation = arm.localRotation;
			}
		}

		private static readonly FieldInfo HeadField = AccessTools.Field(typeof(Character), "m_head");

		private static readonly Action<Character, bool> SetCharacterVisible = AccessTools.MethodDelegate<Action<Character, bool>>(AccessTools.Method(typeof(Character), "SetVisible", new Type[1] { typeof(bool) }, (Type[])null), (object)null, true);

		private static readonly FieldInfo LeftHeldItemField = AccessTools.Field(typeof(VisEquipment), "m_leftItemInstance");

		private static readonly FieldInfo RightHeldItemField = AccessTools.Field(typeof(VisEquipment), "m_rightItemInstance");

		private static readonly FieldInfo[] AttachmentFields = new FieldInfo[3]
		{
			AccessTools.Field(typeof(VisEquipment), "m_helmetItemInstance"),
			AccessTools.Field(typeof(VisEquipment), "m_hairItemInstance"),
			AccessTools.Field(typeof(VisEquipment), "m_beardItemInstance")
		};

		private readonly Dictionary<Renderer, bool> _hidden = new Dictionary<Renderer, bool>();

		private readonly Dictionary<Transform, ArmPose> _armPoses = new Dictionary<Transform, ArmPose>();

		private readonly Dictionary<SkinnedMeshRenderer, bool> _skinUpdates = new Dictionary<SkinnedMeshRenderer, bool>();

		private readonly HashSet<Camera> _suspendedCameras = new HashSet<Camera>();

		private GameObject? _heldItem;

		private Vector3 _gripAdjustment;

		private Animator? _animator;

		private AnimatorCullingMode _originalCullingMode;

		private Transform? _leftArm;

		private Transform? _rightArm;

		private Player? _armPlayer;

		private Camera? _camera;

		private Camera? _skyCamera;

		private Player? _player;

		private Transform? _hiddenHead;

		private Vector3 _headScale;

		private float _originalNearClip;

		private float _originalFov;

		private float _originalSkyFov;

		internal bool IsActiveFor(Character character)
		{
			if ((Object)(object)_camera != (Object)null && (Object)(object)_player != (Object)null && (Object)(object)_player == (Object)(object)character && DadsFPPPlugin.Enabled.Value)
			{
				return DadsFPPPlugin.FirstPerson.Value;
			}
			return false;
		}

		internal void Subscribe()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(BeforeRender));
			Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(AfterRender));
			RenderPipelineManager.beginCameraRendering += BeforePipelineRender;
			RenderPipelineManager.endCameraRendering += AfterPipelineRender;
		}

		internal void Unsubscribe()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Restore();
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(BeforeRender));
			Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(AfterRender));
			RenderPipelineManager.beginCameraRendering -= BeforePipelineRender;
			RenderPipelineManager.endCameraRendering -= AfterPipelineRender;
		}

		internal void Update(GameCamera gameCamera, Camera camera, Player? player, bool freeFly)
		{
			//IL_00fd: 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)
			RestoreVisibility();
			if (!DadsFPPPlugin.Enabled.Value || !DadsFPPPlugin.FirstPerson.Value || (Object)(object)camera == (Object)null || (Object)(object)player == (Object)null || (Object)(object)((Character)player).m_eye == (Object)null || freeFly || ((Character)player).IsDead() || ((Character)player).InCutscene() || ((Character)player).IsTeleporting())
			{
				Restore();
				return;
			}
			if ((Object)(object)_camera != (Object)(object)camera)
			{
				Restore();
				_camera = camera;
				_skyCamera = gameCamera.m_skyCamera;
				_originalNearClip = camera.nearClipPlane;
				_originalFov = camera.fieldOfView;
				if ((Object)(object)_skyCamera != (Object)null)
				{
					_originalSkyFov = _skyCamera.fieldOfView;
				}
			}
			if ((Object)(object)_player != (Object)(object)player)
			{
				RestoreAnimationUpdates();
				_player = player;
				_animator = ((Component)player).GetComponentInChildren<Animator>();
				if ((Object)(object)_animator != (Object)null)
				{
					_originalCullingMode = _animator.cullingMode;
					_animator.cullingMode = (AnimatorCullingMode)0;
				}
				SkinnedMeshRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(true);
				foreach (SkinnedMeshRenderer val in componentsInChildren)
				{
					_skinUpdates.Add(val, val.updateWhenOffscreen);
					val.updateWhenOffscreen = true;
				}
			}
			PositionAtEyes(camera, player);
			camera.fieldOfView = DadsFPPPlugin.FieldOfView.Value;
			camera.nearClipPlane = DadsFPPPlugin.NearClip.Value;
			if ((Object)(object)_skyCamera != (Object)null)
			{
				_skyCamera.fieldOfView = camera.fieldOfView;
			}
			SetCharacterVisible((Character)(object)player, arg2: true);
			UpdateToolGrip(camera, player);
			HideHeadForCamera(player, ((Humanoid)player).GetVisEquipment());
		}

		internal void Restore()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			RestoreVisibility();
			RestoreAnimationUpdates();
			if ((Object)(object)_camera != (Object)null)
			{
				_camera.nearClipPlane = _originalNearClip;
				_camera.fieldOfView = _originalFov;
			}
			if ((Object)(object)_skyCamera != (Object)null)
			{
				_skyCamera.fieldOfView = _originalSkyFov;
			}
			_camera = null;
			_skyCamera = null;
			_player = null;
			_armPlayer = null;
			_leftArm = null;
			_rightArm = null;
			_heldItem = null;
			_gripAdjustment = Vector3.zero;
			_suspendedCameras.Clear();
		}

		private void BeforePipelineRender(ScriptableRenderContext context, Camera camera)
		{
			BeforeRender(camera);
		}

		private void AfterPipelineRender(ScriptableRenderContext context, Camera camera)
		{
			AfterRender(camera);
		}

		private void BeforeRender(Camera camera)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camera != (Object)(object)_camera)
			{
				if (_armPoses.Count > 0 || (Object)(object)_hiddenHead != (Object)null || _hidden.Count > 0)
				{
					RestoreVisibility();
					_suspendedCameras.Add(camera);
				}
				return;
			}
			RestoreVisibility();
			if ((Object)(object)camera != (Object)(object)_camera || (Object)(object)_player == (Object)null)
			{
				return;
			}
			PositionAtEyes(camera, _player);
			UpdateToolGrip(camera, _player);
			VisEquipment visEquipment = ((Humanoid)_player).GetVisEquipment();
			if (DadsFPPPlugin.ShowArmsAndWeapons.Value && (Object)(object)visEquipment != (Object)null)
			{
				if ((Object)(object)_armPlayer != (Object)(object)_player || (Object)(object)_leftArm == (Object)null || (Object)(object)_rightArm == (Object)null)
				{
					_armPlayer = _player;
					_leftArm = FindUpperArm(visEquipment.m_leftHand);
					_rightArm = FindUpperArm(visEquipment.m_rightHand);
				}
				Quaternion viewRotation = Quaternion.FromToRotation(((Component)_player).transform.forward, ((Component)camera).transform.forward);
				Vector3 firstPersonEyePoint = GetFirstPersonEyePoint(_player);
				Vector3 offset = ((Component)camera).transform.TransformDirection(DadsFPPPlugin.ArmViewOffset.Value + _gripAdjustment);
				PoseArm(_leftArm, firstPersonEyePoint, viewRotation, offset);
				PoseArm(_rightArm, firstPersonEyePoint, viewRotation, offset);
			}
			HideHeadForCamera(_player, visEquipment);
		}

		private static Vector3 GetFirstPersonEyePoint(Player player)
		{
			//IL_0022: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			object? value = HeadField.GetValue(player);
			Transform val = (Transform)((value is Transform) ? value : null);
			if (!((Object)(object)val != (Object)null))
			{
				return ((Character)player).GetEyePoint();
			}
			return val.position + ((Component)player).transform.up * 0.14f;
		}

		private static void PositionAtEyes(Camera camera, Player player)
		{
			//IL_0007: 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_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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			((Component)camera).transform.position = GetFirstPersonEyePoint(player) + ((Component)camera).transform.forward * DadsFPPPlugin.ForwardOffset.Value + Vector3.up * (0.2f + DadsFPPPlugin.VerticalOffset.Value);
		}

		private void HideHeadForCamera(Player player, VisEquipment? equipment)
		{
			//IL_0038: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!DadsFPPPlugin.HideHead.Value)
			{
				return;
			}
			ref Transform? hiddenHead = ref _hiddenHead;
			object? value = HeadField.GetValue(player);
			hiddenHead = (Transform?)((value is Transform) ? value : null);
			if ((Object)(object)_hiddenHead != (Object)null)
			{
				_headScale = _hiddenHead.localScale;
				_hiddenHead.localScale = Vector3.zero;
			}
			if ((Object)(object)equipment == (Object)null)
			{
				return;
			}
			FieldInfo[] attachmentFields = AttachmentFields;
			for (int i = 0; i < attachmentFields.Length; i++)
			{
				object? value2 = attachmentFields[i].GetValue(equipment);
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val2 in componentsInChildren)
				{
					if (!_hidden.ContainsKey(val2))
					{
						_hidden.Add(val2, val2.forceRenderingOff);
						val2.forceRenderingOff = true;
					}
				}
			}
		}

		private void AfterRender(Camera camera)
		{
			if ((Object)(object)camera == (Object)(object)_camera)
			{
				RestoreVisibility();
			}
			else if (_suspendedCameras.Remove(camera) && (Object)(object)_camera != (Object)null)
			{
				BeforeRender(_camera);
			}
		}

		private void UpdateToolGrip(Camera camera, Player player)
		{
			//IL_0024: 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_00a3: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			VisEquipment visEquipment = ((Humanoid)player).GetVisEquipment();
			if (!DadsFPPPlugin.ShowArmsAndWeapons.Value || (Object)(object)visEquipment == (Object)null)
			{
				_heldItem = null;
				_gripAdjustment = Vector3.zero;
				return;
			}
			object? value = RightHeldItemField.GetValue(visEquipment);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			object? value2 = LeftHeldItemField.GetValue(visEquipment);
			GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null);
			GameObject val3 = (((Object)(object)val != (Object)null && val.activeInHierarchy) ? val : val2);
			Transform val4 = (((Object)(object)val3 == (Object)(object)val) ? visEquipment.m_rightHand : visEquipment.m_leftHand);
			if ((Object)(object)val3 == (Object)null || !val3.activeInHierarchy || (Object)(object)val4 == (Object)null)
			{
				_heldItem = null;
				_gripAdjustment = Vector3.zero;
				return;
			}
			bool num = (Object)(object)_heldItem != (Object)(object)val3;
			_heldItem = val3;
			if (num || (!((Character)player).InAttack() && !((Character)player).IsBlocking() && !((Character)player).IsDrawingBow() && !((Character)player).InDodge()))
			{
				Quaternion val5 = Quaternion.FromToRotation(((Component)player).transform.forward, ((Component)camera).transform.forward);
				Vector3 firstPersonEyePoint = GetFirstPersonEyePoint(player);
				Vector3 val6 = ((Component)camera).transform.InverseTransformPoint(firstPersonEyePoint + val5 * (val4.position - firstPersonEyePoint)) + DadsFPPPlugin.ArmViewOffset.Value;
				ToolGripFraming.Fit(val6.x, val6.y, val6.z, camera.fieldOfView, camera.aspect, out var visibleX, out var visibleY, out var visibleZ);
				Vector3 val7 = default(Vector3);
				((Vector3)(ref val7))..ctor(visibleX, visibleY, visibleZ);
				_gripAdjustment = val7 - val6;
			}
		}

		private static Transform? FindUpperArm(Transform? hand)
		{
			for (Transform val = hand; (Object)(object)val != (Object)null; val = val.parent)
			{
				string text = ((Object)val).name.Replace("_", "").Replace(" ", "").ToLowerInvariant();
				if (!text.Contains("upperarm") && !text.EndsWith("leftarm") && !text.EndsWith("rightarm"))
				{
					switch (text)
					{
					case "arml":
					case "armr":
					case "larm":
					case "rarm":
						break;
					default:
						continue;
					}
				}
				return val;
			}
			return null;
		}

		private void PoseArm(Transform? arm, Vector3 eyePoint, Quaternion viewRotation, Vector3 offset)
		{
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)arm == (Object)null) && !_armPoses.ContainsKey(arm))
			{
				_armPoses.Add(arm, new ArmPose(arm));
				Vector3 position = arm.position;
				Quaternion rotation = arm.rotation;
				arm.position = eyePoint + viewRotation * (position - eyePoint) + offset;
				arm.rotation = viewRotation * rotation;
			}
		}

		private void RestoreVisibility()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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)
			foreach (KeyValuePair<Transform, ArmPose> armPose in _armPoses)
			{
				if (!((Object)(object)armPose.Key == (Object)null))
				{
					armPose.Key.localPosition = armPose.Value.Position;
					armPose.Key.localRotation = armPose.Value.Rotation;
				}
			}
			_armPoses.Clear();
			if ((Object)(object)_hiddenHead != (Object)null)
			{
				_hiddenHead.localScale = _headScale;
			}
			_hiddenHead = null;
			foreach (KeyValuePair<Renderer, bool> item in _hidden)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					item.Key.forceRenderingOff = item.Value;
				}
			}
			_hidden.Clear();
		}

		private void RestoreAnimationUpdates()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_animator != (Object)null)
			{
				_animator.cullingMode = _originalCullingMode;
			}
			_animator = null;
			foreach (KeyValuePair<SkinnedMeshRenderer, bool> skinUpdate in _skinUpdates)
			{
				if ((Object)(object)skinUpdate.Key != (Object)null)
				{
					skinUpdate.Key.updateWhenOffscreen = skinUpdate.Value;
				}
			}
			_skinUpdates.Clear();
		}
	}
	internal sealed class HealthReadout
	{
		private readonly struct Entry
		{
			internal readonly string Text;

			internal readonly Color Color;

			internal readonly float Expires;

			internal Entry(float change)
			{
				//IL_0064: 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_0069: Unknown result type (might be due to invalid IL or missing references)
				bool flag = change > 0f;
				Text = (flag ? "Healed +" : "Damage -") + Mathf.Abs(change).ToString("0.##", CultureInfo.InvariantCulture);
				Color = (flag ? new Color(0.45f, 1f, 0.5f) : new Color(1f, 0.4f, 0.35f));
				Expires = Time.unscaledTime + 4f;
			}
		}

		private readonly List<Entry> _entries = new List<Entry>();

		private GUIStyle? _label;

		internal void Record(float change)
		{
			if (!float.IsNaN(change) && !float.IsInfinity(change) && !(Mathf.Abs(change) < 0.001f))
			{
				_entries.RemoveAll((Entry entry) => entry.Expires <= Time.unscaledTime);
				_entries.Insert(0, new Entry(change));
				if (_entries.Count > 3)
				{
					_entries.RemoveAt(3);
				}
			}
		}

		internal void Draw(FirstPersonCamera controller)
		{
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Invalid comparison between Unknown and I4
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00b3: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !controller.IsActiveFor((Character)(object)localPlayer))
			{
				_entries.Clear();
				return;
			}
			_entries.RemoveAll((Entry entry) => entry.Expires <= Time.unscaledTime);
			if (_entries.Count == 0 || (Object)(object)Hud.instance == (Object)null || !Hud.instance.IsVisible() || (int)Event.current.type != 7)
			{
				return;
			}
			if (_label == null)
			{
				_label = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4
				};
				_label.normal.textColor = Color.white;
			}
			float num = Mathf.Clamp((float)Screen.height / 1080f, 0.65f, 2f);
			float num2 = 160f * num;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor((float)Screen.width - num2 - 24f * num, ((float)Screen.height - num2) * 0.5f, num2, num2);
			Color color = GUI.color;
			try
			{
				GUI.color = new Color(0.75f, 0.75f, 0.75f, 0.85f);
				GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = new Color(0.035f, 0.035f, 0.035f, 0.9f);
				GUI.DrawTexture(new Rect(((Rect)(ref val)).x + num, ((Rect)(ref val)).y + num, num2 - 2f * num, num2 - 2f * num), (Texture)(object)Texture2D.whiteTexture);
				_label.fontSize = Mathf.RoundToInt(19f * num);
				float num3 = 42f * num;
				float num4 = ((Rect)(ref val)).y + (num2 - num3 * (float)_entries.Count) * 0.5f;
				for (int num5 = 0; num5 < _entries.Count; num5++)
				{
					GUI.color = _entries[num5].Color;
					GUI.Label(new Rect(((Rect)(ref val)).x + 6f * num, num4 + (float)num5 * num3, num2 - 12f * num, num3), _entries[num5].Text, _label);
				}
			}
			finally
			{
				GUI.color = color;
			}
		}
	}
	[HarmonyPatch]
	internal static class HealthChangePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Character), "ApplyDamage", new Type[4]
			{
				typeof(HitData),
				typeof(bool),
				typeof(bool),
				typeof(DamageModifier)
			}, (Type[])null);
			yield return AccessTools.Method(typeof(Character), "RPC_Heal", new Type[3]
			{
				typeof(long),
				typeof(float),
				typeof(bool)
			}, (Type[])null);
		}

		private static void Prefix(Character __instance, out float __state)
		{
			DadsFPPPlugin? instance = DadsFPPPlugin.Instance;
			__state = ((instance != null && instance.Controller.IsActiveFor(__instance)) ? Mathf.Max(0f, __instance.GetHealth()) : float.NaN);
		}

		private static void Postfix(Character __instance, float __state)
		{
			if (!float.IsNaN(__state))
			{
				DadsFPPPlugin? instance = DadsFPPPlugin.Instance;
				if (instance != null && instance.Controller.IsActiveFor(__instance))
				{
					DadsFPPPlugin.Instance.HealthNumbers.Record(Mathf.Max(0f, __instance.GetHealth()) - __state);
				}
			}
		}
	}
	internal static class ToolGripFraming
	{
		internal static void Fit(float x, float y, float z, float fieldOfView, float aspect, out float visibleX, out float visibleY, out float visibleZ)
		{
			visibleZ = Math.Max(0.65f, z);
			float num = visibleZ * (float)Math.Tan((double)fieldOfView * Math.PI / 360.0);
			float num2 = Math.Min(0.3f, num * aspect * 0.6f);
			visibleX = Math.Max(0f - num2, Math.Min(num2, x));
			visibleY = Math.Max((0f - num) * 0.6f, Math.Min((0f - num) * 0.25f, y));
		}
	}
}