Decompiled source of FreeflySpeedControl v2.1.0

plugins/FreeflySpeedControl.dll

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

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("FreeflySpeedControl")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FreeflySpeedControl")]
[assembly: AssemblyTitle("FreeflySpeedControl")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 FreeflySpeedControl
{
	[BepInPlugin("com.mitch.freeflyspeedcontrol", "Freefly Speed Control", "2.1.0")]
	public class FreeflySpeedControlPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(GameCamera), "UpdateFreeFly")]
		public class FreeFlyTranspiler
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				bool flag = false;
				for (int i = 0; i < list.Count - 2; i++)
				{
					if (list[i].opcode == OpCodes.Ldc_R4 && list[i].operand is float num && Mathf.Approximately(num, 1f) && list[i + 1].opcode == OpCodes.Ldc_R4 && list[i + 1].operand is float num2 && Mathf.Approximately(num2, 1000f) && list[i + 2].opcode == OpCodes.Call && list[i + 2].operand is MethodInfo methodInfo && methodInfo.Name == "Clamp")
					{
						list[i].operand = minSpeed.Value;
						list[i + 1].operand = maxSpeed.Value;
						flag = true;
						FreeflySpeedControlPlugin instance = FreeflySpeedControlPlugin.instance;
						if (instance != null)
						{
							((BaseUnityPlugin)instance).Logger.LogInfo((object)($"Transpiler: Patched Clamp({num}, {num2}) " + $"→ Clamp({minSpeed.Value}, {maxSpeed.Value})"));
						}
						break;
					}
				}
				if (!flag)
				{
					FreeflySpeedControlPlugin instance2 = FreeflySpeedControlPlugin.instance;
					if (instance2 != null)
					{
						((BaseUnityPlugin)instance2).Logger.LogWarning((object)"Transpiler: Could not find Clamp(1f, 1000f) pattern!");
					}
				}
				return list;
			}
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateFreeFly")]
		public class FreeFlyMousePatch
		{
			private static Quaternion rotationBefore;

			private static FieldInfo speedField;

			private static bool fieldSearchDone;

			private static void Prefix(GameCamera __instance)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				if (linkMouseToSpeed.Value)
				{
					rotationBefore = ((Component)__instance).transform.rotation;
				}
			}

			private static void Postfix(GameCamera __instance)
			{
				//IL_00b9: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: 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_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				if (!linkMouseToSpeed.Value)
				{
					return;
				}
				if (!fieldSearchDone)
				{
					speedField = typeof(GameCamera).GetField("m_freeFlySpeed", BindingFlags.Instance | BindingFlags.NonPublic);
					fieldSearchDone = true;
				}
				if (!(speedField == null))
				{
					float num = (float)speedField.GetValue(__instance);
					float num2 = num / maxSpeed.Value;
					float num3 = Mathf.Lerp(1f, num2, mouseLinkStrength.Value);
					num3 = Mathf.Max(num3, 0.02f);
					if (!Mathf.Approximately(num3, 1f))
					{
						Quaternion rotation = ((Component)__instance).transform.rotation;
						Quaternion val = rotation * Quaternion.Inverse(rotationBefore);
						Quaternion val2 = Quaternion.Slerp(Quaternion.identity, val, num3);
						((Component)__instance).transform.rotation = val2 * rotationBefore;
					}
				}
			}
		}

		public static ConfigEntry<float> minSpeed;

		public static ConfigEntry<float> maxSpeed;

		public static ConfigEntry<bool> linkMouseToSpeed;

		public static ConfigEntry<float> mouseLinkStrength;

		private static FreeflySpeedControlPlugin instance;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			instance = this;
			minSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Speed", "MinSpeed", 0.05f, "Minimum freefly movement speed. Vanilla is 1.0. 0.05 = ultra-slow cinematic crawl.");
			maxSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Speed", "MaxSpeed", 50f, "Maximum freefly movement speed. Vanilla is 1000. 50 = fast but controlled. Raise if you need to cover ground quickly.");
			linkMouseToSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Mouse", "LinkMouseToSpeed", true, "When true, mouse look speed automatically scales with movement speed. Slow movement = slow mouse look. Fast movement = normal mouse look. One scroll wheel controls everything.");
			mouseLinkStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Mouse", "MouseLinkStrength", 0.7f, "How tightly mouse look follows movement speed (0.0 to 1.0). 1.0 = fully linked (mouse slows down exactly as much as movement). 0.5 = partially linked (mouse slows less than movement). 0.0 = not linked (mouse always at vanilla speed).");
			harmony = new Harmony("com.mitch.freeflyspeedcontrol");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Freefly Speed Control v2.1.0 loaded!");
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"  MinSpeed: {minSpeed.Value}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"  MaxSpeed: {maxSpeed.Value}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"  LinkMouseToSpeed: {linkMouseToSpeed.Value}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"  MouseLinkStrength: {mouseLinkStrength.Value}");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}