Decompiled source of ReLegend 3rd Person v0.2.1

ReLegendThirdPerson.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cinemachine;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("ReLegendThirdPerson")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1")]
[assembly: AssemblyProduct("ReLegendThirdPerson")]
[assembly: AssemblyTitle("ReLegendThirdPerson")]
[assembly: AssemblyVersion("0.2.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ReLegendThirdPerson
{
	[HarmonyPatch]
	internal static class CameraPatches
	{
		[HarmonyPatch(typeof(MinimapCamera), "Update")]
		[HarmonyPostfix]
		private static void MinimapCamera_Update_Postfix()
		{
			if (ThirdPersonRig.Active && Plugin.Enabled.Value)
			{
				MinimapCamera.yRot = 0f;
			}
		}
	}
	internal static class DepthOfFieldControl
	{
		private static float _lastApplied = float.NaN;

		private static bool _lastEnabled;

		private static bool _warned;

		internal static void Tick()
		{
			try
			{
				CameraManager instance = CameraManager.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				bool value = Plugin.DofEnabled.Value;
				Behaviour val = Reflect.Get<Behaviour>(typeof(CameraManager), "depthOfField", instance);
				if ((Object)(object)val == (Object)null)
				{
					if (!_warned)
					{
						_warned = true;
						Plugin.Log.LogWarning((object)"No depth-of-field effect on CameraManager; DOF control is inert.");
					}
					return;
				}
				if (val.enabled != value)
				{
					val.enabled = value;
					_lastEnabled = value;
					_lastApplied = float.NaN;
				}
				if (value)
				{
					float num = Mathf.Clamp01(Plugin.DofIntensity.Value);
					float num2 = (Plugin.DofAutoFocus.Value ? Mathf.Max(0.1f, Plugin.Distance.Value) : Plugin.DofFocalLength.Value);
					float value2 = Plugin.DofFocalSize.Value;
					float num3 = num * Mathf.Max(0f, Plugin.DofMaxAperture.Value);
					float num4 = num2 * 1000f + value2 * 100f + num3;
					if (float.IsNaN(_lastApplied) || !Mathf.Approximately(num4, _lastApplied))
					{
						_lastApplied = num4;
						instance.SetDoF(num2, value2, num3);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Depth-of-field update failed: " + ex));
			}
		}

		internal static void Reset()
		{
			_lastApplied = float.NaN;
			_lastEnabled = false;
		}
	}
	[HarmonyPatch]
	internal static class FacingPatches
	{
		[HarmonyPatch(typeof(MovementPlayer), "MovementDirection")]
		[HarmonyPostfix]
		private static void MovementDirection_Postfix(MovementPlayer __instance)
		{
			if (!Plugin.Enabled.Value || !Plugin.FacingFollowsInput.Value || !ThirdPersonRig.Active || (Plugin.FacingFreezeWhileOrbiting.Value && Plugin.RequireRightMouse.Value && Input.GetMouseButton(1)))
			{
				return;
			}
			try
			{
				Apply(__instance);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Facing update failed: " + ex));
			}
		}

		private static void Apply(MovementPlayer move)
		{
			//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_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_0062: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			Vector3 moveDirection = move._moveDirection;
			moveDirection.y = 0f;
			if (!(((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f))
			{
				PlayerHandler val = (((Object)(object)GameManager.instance != (Object)null) ? GameManager.instance.player : null);
				if (!((Object)(object)val == (Object)null) && ShouldTurn(val))
				{
					Transform transform = ((Component)val).transform;
					Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref moveDirection)).normalized);
					float num = Mathf.Max(1f, Plugin.FacingTurnSpeed.Value) * Time.deltaTime;
					transform.rotation = Quaternion.RotateTowards(transform.rotation, val2, num);
				}
			}
		}

		private static bool ShouldTurn(PlayerHandler hero)
		{
			try
			{
				AttackPlayer attack = hero.Attack;
				if ((Object)(object)attack != (Object)null)
				{
					if (attack.isAttacking)
					{
						return false;
					}
					if (Reflect.Get<bool>(typeof(AttackPlayer), "isMining", attack))
					{
						return false;
					}
					if (Reflect.Get<bool>(typeof(AttackPlayer), "isRolling", attack))
					{
						return false;
					}
				}
				FarmActionPlayer farmAction = hero.farmAction;
				if ((Object)(object)farmAction != (Object)null && (farmAction.IsWatering || farmAction.IsHoe))
				{
					return false;
				}
				MovementPlayer movement = hero.Movement;
				if ((Object)(object)movement != (Object)null && movement.isSwim)
				{
					return false;
				}
				TamingPlayer taming = hero.Taming;
				if ((Object)(object)taming != (Object)null && taming.isMounted)
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("com.community.relegend.thirdperson", "Re:Legend Third Person", "0.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.community.relegend.thirdperson";

		public const string NAME = "Re:Legend Third Person";

		public const string VERSION = "0.2.1";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		private Harmony _harmony;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyboardShortcut> ToggleKey;

		internal static ConfigEntry<float> ShoulderOffset;

		internal static ConfigEntry<float> ShoulderHeight;

		internal static ConfigEntry<float> Distance;

		internal static ConfigEntry<float> DistanceMin;

		internal static ConfigEntry<float> DistanceMax;

		internal static ConfigEntry<float> ZoomStep;

		internal static ConfigEntry<float> Pitch;

		internal static ConfigEntry<float> PitchMin;

		internal static ConfigEntry<float> PitchMax;

		internal static ConfigEntry<float> Fov;

		internal static ConfigEntry<float> SensitivityX;

		internal static ConfigEntry<float> SensitivityY;

		internal static ConfigEntry<bool> InvertY;

		internal static ConfigEntry<bool> RequireRightMouse;

		internal static ConfigEntry<bool> FacingFollowsInput;

		internal static ConfigEntry<float> FacingTurnSpeed;

		internal static ConfigEntry<bool> FacingFreezeWhileOrbiting;

		internal static ConfigEntry<bool> DofEnabled;

		internal static ConfigEntry<float> DofIntensity;

		internal static ConfigEntry<bool> DofAutoFocus;

		internal static ConfigEntry<float> DofFocalLength;

		internal static ConfigEntry<float> DofFocalSize;

		internal static ConfigEntry<float> DofMaxAperture;

		internal static ConfigEntry<bool> TargetingEnabled;

		internal static ConfigEntry<KeyboardShortcut> TargetNextKey;

		internal static ConfigEntry<KeyboardShortcut> TargetClearKey;

		internal static ConfigEntry<float> TargetMaxRange;

		internal static ConfigEntry<bool> TargetRequireOnScreen;

		private void Awake()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. Turning this off hands the camera straight back to the game.");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)286, Array.Empty<KeyCode>()), "Switches between third person and the vanilla camera in-game.");
			ShoulderOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "ShoulderOffset", 0.6f, "Sideways offset from the player. Positive is over the right shoulder,\nnegative the left, 0 is centred behind.");
			ShoulderHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "ShoulderHeight", 1.6f, "Height of the look-at pivot above the player's feet, roughly head height.");
			Distance = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "Distance", 4.5f, "Current camera distance. Updated as you zoom.");
			DistanceMin = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "DistanceMin", 1.2f, "Closest zoom. Around 1.2 is close over-the-shoulder.");
			DistanceMax = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "DistanceMax", 18f, "Furthest zoom. Large values approach the vanilla pulled-back feel.");
			ZoomStep = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "ZoomStep", 1.1f, "Distance change per mouse-wheel notch.");
			Pitch = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "Pitch", 18f, "Starting downward pitch in degrees.");
			PitchMin = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "PitchMin", -25f, "Highest the camera can look up.");
			PitchMax = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "PitchMax", 70f, "Lowest the camera can look down. Steep values approach a top-down view.");
			Fov = ((BaseUnityPlugin)this).Config.Bind<float>("Rig", "FieldOfView", 55f, "Vertical field of view for the third-person camera.");
			SensitivityX = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "SensitivityX", 3.2f, "Horizontal look speed.");
			SensitivityY = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "SensitivityY", 2.2f, "Vertical look speed.");
			InvertY = ((BaseUnityPlugin)this).Config.Bind<bool>("Look", "InvertY", false, "Invert vertical look.");
			RequireRightMouse = ((BaseUnityPlugin)this).Config.Bind<bool>("Look", "HoldRightMouseToRotate", true, "Rotate only while right mouse is held. Turning this off gives free look,\nwhich conflicts with cursor-driven aiming and menu clicks.");
			FacingFollowsInput = ((BaseUnityPlugin)this).Config.Bind<bool>("Facing", "FollowMovementInput", true, "Turn the character to face the movement keys, independently of the camera.\nCamera orbit on its own never changes facing; only pressing a direction does.");
			FacingTurnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Facing", "TurnSpeed", 720f, "Degrees per second. Vanilla lerps at rotateRate 3, which visibly lags behind\nthe keys once the camera can swing freely. Lower this for a heavier feel.");
			FacingFreezeWhileOrbiting = ((BaseUnityPlugin)this).Config.Bind<bool>("Facing", "FreezeWhileOrbiting", true, "While right mouse is held the camera orbits and the character keeps its\nfacing. Movement input is camera-relative, so without this holding a\ndirection key while orbiting drags the body around with the camera.");
			DofEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("DepthOfField", "Enabled", false, "Take over the game's depth-of-field effect. Off leaves the scene's own\nsettings completely untouched.");
			DofIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("DepthOfField", "Intensity", 0.35f, "0 to 1. Scales the aperture, which is what controls how strongly the\nbackground blurs.");
			DofAutoFocus = ((BaseUnityPlugin)this).Config.Bind<bool>("DepthOfField", "AutoFocusPlayer", true, "Track focal length to the current camera distance so the character stays\nsharp as you zoom. Turn off to set the focal length by hand.");
			DofFocalLength = ((BaseUnityPlugin)this).Config.Bind<float>("DepthOfField", "FocalLength", 4.5f, "Manual focus distance, used only when AutoFocusPlayer is off.");
			DofFocalSize = ((BaseUnityPlugin)this).Config.Bind<float>("DepthOfField", "FocalSize", 0.05f, "Size of the in-focus band. Larger keeps more of the scene sharp.");
			DofMaxAperture = ((BaseUnityPlugin)this).Config.Bind<float>("DepthOfField", "MaxAperture", 2.5f, "Aperture at Intensity 1.0. Raise for a more extreme blur ceiling.");
			TargetingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "Enabled", false, "Tab targeting. Currently selection and tracking only: it picks a target and\nthe camera can orbit around it, but it does not yet redirect attacks.\nSee the README for why that part is not done blind.");
			TargetNextKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Targeting", "NextTargetKey", new KeyboardShortcut((KeyCode)9, Array.Empty<KeyCode>()), "Cycle to the next valid target.");
			TargetClearKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Targeting", "ClearTargetKey", new KeyboardShortcut((KeyCode)27, Array.Empty<KeyCode>()), "Drop the current target.");
			TargetMaxRange = ((BaseUnityPlugin)this).Config.Bind<float>("Targeting", "MaxRange", 25f, "Maximum distance for a target to be selectable.");
			TargetRequireOnScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("Targeting", "RequireOnScreen", true, "Only cycle through targets currently visible on screen.");
			_harmony = new Harmony("com.community.relegend.thirdperson");
			try
			{
				_harmony.PatchAll(typeof(CameraPatches));
				_harmony.PatchAll(typeof(FacingPatches));
				Log.LogInfo((object)("Re:Legend Third Person 0.2.1 loaded. BepInEx " + typeof(BaseUnityPlugin).Assembly.GetName().Version?.ToString() + ", Harmony " + typeof(Harmony).Assembly.GetName().Version?.ToString() + "."));
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Patching failed, mod is inert: " + ex));
			}
		}

		private void OnDestroy()
		{
			ThirdPersonRig.Teardown();
			DepthOfFieldControl.Reset();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			//IL_0005: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				KeyboardShortcut value = ToggleKey.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					value = ToggleKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						Enabled.Value = !Enabled.Value;
						SaveConfig();
						Log.LogInfo((object)("Third person " + (Enabled.Value ? "enabled." : "disabled.")));
					}
				}
				ThirdPersonRig.Tick();
				Targeting.Tick();
				DepthOfFieldControl.Tick();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Update failed: " + ex));
			}
		}

		internal static IEnumerable<KeyValuePair<string, ConfigEntry<bool>>> Features()
		{
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Third person camera", Enabled);
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Invert vertical look", InvertY);
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Hold RMB to rotate", RequireRightMouse);
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Facing follows movement", FacingFollowsInput);
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Freeze facing while orbiting", FacingFreezeWhileOrbiting);
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Depth of field", DofEnabled);
			yield return new KeyValuePair<string, ConfigEntry<bool>>("Tab targeting", TargetingEnabled);
		}

		internal static void SaveConfig()
		{
			try
			{
				((BaseUnityPlugin)Instance).Config.Save();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not save config: " + ex));
			}
		}
	}
	internal static class Reflect
	{
		private static readonly Dictionary<string, FieldInfo> Cache = new Dictionary<string, FieldInfo>();

		private static readonly HashSet<string> Reported = new HashSet<string>();

		private static FieldInfo Find(Type type, string name)
		{
			string text = type.FullName + "::" + name;
			if (Cache.TryGetValue(text, out var value))
			{
				return value;
			}
			value = AccessTools.Field(type, name);
			Cache[text] = value;
			if (value == null && Reported.Add(text))
			{
				Plugin.Log.LogError((object)("Field not found: " + text + ". The game may have been updated."));
			}
			return value;
		}

		internal static T Get<T>(Type type, string name, object instance)
		{
			FieldInfo fieldInfo = Find(type, name);
			if (fieldInfo == null)
			{
				return default(T);
			}
			try
			{
				object value = fieldInfo.GetValue(instance);
				return (value is T) ? ((T)value) : default(T);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Reading " + type.Name + "." + name + " failed: " + ex.Message));
				return default(T);
			}
		}

		internal static void Set(Type type, string name, object instance, object value)
		{
			FieldInfo fieldInfo = Find(type, name);
			if (fieldInfo == null)
			{
				return;
			}
			try
			{
				fieldInfo.SetValue(instance, value);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Writing " + type.Name + "." + name + " failed: " + ex.Message));
			}
		}

		internal static bool Invoke(Type type, string name, object instance)
		{
			MethodInfo methodInfo = AccessTools.Method(type, name, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Plugin.Log.LogError((object)("Method not found: " + type.FullName + "::" + name));
				return false;
			}
			try
			{
				methodInfo.Invoke(instance, null);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Invoking " + type.Name + "." + name + " failed: " + ex.Message));
				return false;
			}
		}
	}
	internal static class Targeting
	{
		private static readonly List<MonsterDamage> Candidates = new List<MonsterDamage>();

		private static MonsterDamage _current;

		private static float _nextRefresh;

		internal static MonsterDamage Current => _current;

		internal static Transform CurrentTransform
		{
			get
			{
				if (!Plugin.TargetingEnabled.Value)
				{
					return null;
				}
				if ((Object)(object)_current == (Object)null)
				{
					_current = null;
					return null;
				}
				return ((Component)_current).transform;
			}
		}

		internal static void Tick()
		{
			//IL_0019: 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_0021: 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_006a: 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_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_0079: 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)
			if (!Plugin.TargetingEnabled.Value)
			{
				_current = null;
				return;
			}
			try
			{
				KeyboardShortcut value = Plugin.TargetClearKey.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					value = Plugin.TargetClearKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						if ((Object)(object)_current != (Object)null)
						{
							Plugin.Log.LogInfo((object)"Target cleared.");
						}
						_current = null;
						return;
					}
				}
				value = Plugin.TargetNextKey.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					value = Plugin.TargetNextKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						CycleTarget();
					}
				}
				if ((Object)(object)_current != (Object)null && !IsValid(_current))
				{
					_current = null;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Targeting failed: " + ex));
				_current = null;
			}
		}

		private static void CycleTarget()
		{
			Refresh();
			if (Candidates.Count == 0)
			{
				_current = null;
				Plugin.Log.LogInfo((object)"No valid targets in range.");
				return;
			}
			int num = (((Object)(object)_current == (Object)null) ? (-1) : Candidates.IndexOf(_current));
			num = (num + 1) % Candidates.Count;
			_current = Candidates[num];
			Plugin.Log.LogInfo((object)("Target: " + ((Object)((Component)_current).gameObject).name + " (" + (num + 1) + "/" + Candidates.Count + ")"));
		}

		private static void Refresh()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime < _nextRefresh && Candidates.Count > 0)
			{
				return;
			}
			_nextRefresh = Time.unscaledTime + 0.5f;
			Candidates.Clear();
			PlayerHandler val = (((Object)(object)GameManager.instance != (Object)null) ? GameManager.instance.player : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MonsterDamage[] array = Object.FindObjectsOfType<MonsterDamage>();
			if (array == null)
			{
				return;
			}
			Vector3 origin = ((Component)val).transform.position;
			foreach (MonsterDamage val2 in array)
			{
				if (IsValid(val2))
				{
					Candidates.Add(val2);
				}
			}
			Candidates.Sort(delegate(MonsterDamage a, MonsterDamage b)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//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_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: 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_0035: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val3 = ((Component)a).transform.position - origin;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				val3 = ((Component)b).transform.position - origin;
				float sqrMagnitude2 = ((Vector3)(ref val3)).sqrMagnitude;
				return sqrMagnitude.CompareTo(sqrMagnitude2);
			});
		}

		private static bool IsValid(MonsterDamage m)
		{
			//IL_0050: 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)
			//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_0091: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m == (Object)null)
			{
				return false;
			}
			if (m.deadMotionStart)
			{
				return false;
			}
			if (!((Component)m).gameObject.activeInHierarchy)
			{
				return false;
			}
			PlayerHandler val = (((Object)(object)GameManager.instance != (Object)null) ? GameManager.instance.player : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Vector3 val2 = ((Component)m).transform.position - ((Component)val).transform.position;
			float value = Plugin.TargetMaxRange.Value;
			if (((Vector3)(ref val2)).sqrMagnitude > value * value)
			{
				return false;
			}
			if (Plugin.TargetRequireOnScreen.Value && !IsOnScreen(((Component)m).transform.position))
			{
				return false;
			}
			return true;
		}

		private static bool IsOnScreen(Vector3 worldPos)
		{
			//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_0019: 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_0033: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return true;
			}
			Vector3 val = main.WorldToViewportPoint(worldPos);
			if (val.z > 0f && val.x >= 0f && val.x <= 1f && val.y >= 0f)
			{
				return val.y <= 1f;
			}
			return false;
		}
	}
	internal static class ThirdPersonRig
	{
		private const int ActivePriority = 5000;

		private const int IdlePriority = -100;

		private static GameObject _rigRoot;

		private static GameObject _vcamObject;

		private static CinemachineVirtualCamera _vcam;

		private static Transform _lookTarget;

		private static float _yaw;

		private static float _pitch;

		private static bool _initialised;

		private static bool _wasActive;

		internal static bool Active { get; private set; }

		internal static float Yaw => _yaw;

		internal static void Tick()
		{
			if (!Plugin.Enabled.Value || VanillaShouldOwnCamera())
			{
				if (_wasActive)
				{
					SetActive(active: false);
				}
				_wasActive = false;
				Active = false;
			}
			else if (EnsureRig())
			{
				if (!_wasActive)
				{
					SetActive(active: true);
					_wasActive = true;
					SeedFromPlayerFacing();
				}
				Active = true;
				ReadLookInput();
				ReadZoomInput();
				ApplyTransform();
			}
		}

		internal static void Teardown()
		{
			try
			{
				if ((Object)(object)_vcamObject != (Object)null)
				{
					Object.Destroy((Object)(object)_vcamObject);
				}
				if ((Object)(object)_rigRoot != (Object)null)
				{
					Object.Destroy((Object)(object)_rigRoot);
				}
			}
			catch
			{
			}
			_vcamObject = null;
			_rigRoot = null;
			_vcam = null;
			_lookTarget = null;
			_initialised = false;
			Active = false;
		}

		private static bool VanillaShouldOwnCamera()
		{
			try
			{
				GameManager instance = GameManager.instance;
				PlayerHandler val = (((Object)(object)instance != (Object)null) ? instance.player : null);
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				if ((Object)(object)val.Taming != (Object)null && (val.Taming.tamingStarted || val.Taming.isMounted))
				{
					return true;
				}
				if ((Object)(object)val.Fishing != (Object)null && val.Fishing.GetFish())
				{
					return true;
				}
				if ((Object)(object)CustomCameraControl.instance == (Object)null)
				{
					return true;
				}
				CameraFollow val2 = Object.FindObjectOfType<CameraFollow>();
				if ((Object)(object)val2 != (Object)null && (val2.cameraTaming || val2.isShopping || val2.fishResult))
				{
					return true;
				}
			}
			catch
			{
				return true;
			}
			return false;
		}

		private static bool EnsureRig()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0076: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			if (_initialised && (Object)(object)_vcam != (Object)null && (Object)(object)_rigRoot != (Object)null)
			{
				return true;
			}
			try
			{
				GameManager instance = GameManager.instance;
				if ((Object)(object)(((Object)(object)instance != (Object)null) ? instance.player : null) == (Object)null)
				{
					return false;
				}
				if ((Object)(object)_rigRoot == (Object)null)
				{
					_rigRoot = new GameObject("ReLegendThirdPerson_Pivot");
					Object.DontDestroyOnLoad((Object)(object)_rigRoot);
					GameObject val = new GameObject("LookTarget");
					val.transform.SetParent(_rigRoot.transform, false);
					_lookTarget = val.transform;
				}
				if ((Object)(object)_vcamObject == (Object)null)
				{
					_vcamObject = new GameObject("ReLegendThirdPerson_VCam");
					Object.DontDestroyOnLoad((Object)(object)_vcamObject);
					_vcam = _vcamObject.AddComponent<CinemachineVirtualCamera>();
					((CinemachineVirtualCameraBase)_vcam).Priority = -100;
					_vcam.m_Lens.FieldOfView = Plugin.Fov.Value;
					((CinemachineVirtualCameraBase)_vcam).Follow = null;
					((CinemachineVirtualCameraBase)_vcam).LookAt = null;
				}
				_initialised = true;
				Plugin.Log.LogInfo((object)"Third-person rig created.");
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not create the third-person rig: " + ex));
				return false;
			}
		}

		private static void SetActive(bool active)
		{
			if (!((Object)(object)_vcam == (Object)null))
			{
				((CinemachineVirtualCameraBase)_vcam).Priority = (active ? 5000 : (-100));
				Plugin.Log.LogInfo((object)("Third-person camera " + (active ? "engaged" : "released") + "."));
			}
		}

		private static void SeedFromPlayerFacing()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerHandler player = GameManager.instance.player;
				if (!((Object)(object)player == (Object)null))
				{
					_yaw = ((Component)player).transform.eulerAngles.y;
					_pitch = Plugin.Pitch.Value;
				}
			}
			catch
			{
			}
		}

		private static void ReadLookInput()
		{
			if (!Plugin.RequireRightMouse.Value || Input.GetMouseButton(1))
			{
				float num = Input.GetAxisRaw("Mouse X") * Plugin.SensitivityX.Value;
				float num2 = Input.GetAxisRaw("Mouse Y") * Plugin.SensitivityY.Value;
				if (Plugin.InvertY.Value)
				{
					num2 = 0f - num2;
				}
				_yaw += num;
				_pitch = Mathf.Clamp(_pitch - num2, Plugin.PitchMin.Value, Plugin.PitchMax.Value);
				if (_yaw > 360f)
				{
					_yaw -= 360f;
				}
				else if (_yaw < 0f)
				{
					_yaw += 360f;
				}
			}
		}

		private static void ReadZoomInput()
		{
			float axisRaw = Input.GetAxisRaw("Mouse ScrollWheel");
			if (!Mathf.Approximately(axisRaw, 0f))
			{
				float num = Plugin.Distance.Value - axisRaw * Plugin.ZoomStep.Value * 10f;
				Plugin.Distance.Value = Mathf.Clamp(num, Plugin.DistanceMin.Value, Plugin.DistanceMax.Value);
			}
		}

		private static void ApplyTransform()
		{
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0111: 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_0124: 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_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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			PlayerHandler player = GameManager.instance.player;
			if ((Object)(object)player == (Object)null || (Object)(object)_vcamObject == (Object)null)
			{
				return;
			}
			Vector3 val = ((Component)player).transform.position + Vector3.up * Plugin.ShoulderHeight.Value;
			Transform currentTransform = Targeting.CurrentTransform;
			if ((Object)(object)currentTransform != (Object)null)
			{
				Vector3 val2 = currentTransform.position - val;
				val2.y = 0f;
				if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
				{
					Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref val2)).normalized);
					_yaw = ((Quaternion)(ref val3)).eulerAngles.y;
				}
			}
			Quaternion val4 = Quaternion.Euler(_pitch, _yaw, 0f);
			Vector3 val5 = val4 * Vector3.right;
			Vector3 val6 = val4 * Vector3.back;
			Vector3 val7 = val + val5 * Plugin.ShoulderOffset.Value;
			Vector3 val8 = val7 + val6 * Plugin.Distance.Value;
			_lookTarget.position = val7;
			_vcamObject.transform.position = val8;
			_vcamObject.transform.rotation = Quaternion.LookRotation(val7 - val8);
			if ((Object)(object)_vcam != (Object)null && !Mathf.Approximately(_vcam.m_Lens.FieldOfView, Plugin.Fov.Value))
			{
				_vcam.m_Lens.FieldOfView = Plugin.Fov.Value;
			}
		}
	}
}