Decompiled source of CrossbowZoom v1.0.0

CrossbowZoom.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("CrossbowZoom")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8e794e21c904e7dafcd4fb57c3a1626e3222ce85")]
[assembly: AssemblyProduct("CrossbowZoom")]
[assembly: AssemblyTitle("CrossbowZoom")]
[assembly: AssemblyVersion("1.0.0.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 CrossbowZoom
{
	internal static class BetterArcheryBridge
	{
		public const string Guid = "ishid4.mods.betterarchery";

		public static FieldRef<int> ZoomState = null;

		public static int ZoomingIn;

		public static FieldRef<float> ZoomInTimer = null;

		public static FieldRef<float> ZoomOutDelayTimer = null;

		public static FieldRef<float> BaseFov = null;

		public static FieldRef<float> LastZoomFov = null;

		public static FieldRef<float> NewZoomFov = null;

		public static ConfigEntry<bool> ZoomEnabled = null;

		public static ConfigEntry<bool> AutomaticZoom = null;

		public static ConfigEntry<float> ZoomFactor = null;

		public static ConfigEntry<float> ZoomConstantTime = null;

		public static Func<bool> IsZoomHeld = null;

		public static Func<Player, bool> TakesInput = null;

		public static string Version { get; private set; } = "not loaded";

		public static bool TryResolve(out string problem)
		{
			if (!Chainloader.PluginInfos.TryGetValue("ishid4.mods.betterarchery", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				problem = "plugin ishid4.mods.betterarchery is not loaded";
				return false;
			}
			Version = value.Metadata.Version.ToString();
			Type type = ((object)value.Instance).GetType().Assembly.GetType("BetterArchery.BetterArchery");
			if (type == null)
			{
				problem = "type BetterArchery.BetterArchery not found";
				return false;
			}
			try
			{
				Type type2 = AccessTools.Inner(type, "ZoomState") ?? throw new MissingMemberException(type.FullName, "ZoomState");
				if (!type2.IsEnum || Enum.GetUnderlyingType(type2) != typeof(int))
				{
					throw new MissingMemberException(type2.FullName + " is not an int enum");
				}
				ZoomingIn = Convert.ToInt32(Enum.Parse(type2, "ZoomingIn"));
				ZoomState = Ref<int>(type, "__ZoomState", type2);
				ZoomInTimer = Ref<float>(type, "ZoomInTimer");
				ZoomOutDelayTimer = Ref<float>(type, "ZoomOutDelayTimer");
				BaseFov = Ref<float>(type, "__BaseFov");
				LastZoomFov = Ref<float>(type, "__LastZoomFov");
				NewZoomFov = Ref<float>(type, "__NewZoomFov");
				ZoomEnabled = Entry<bool>(type, "ConfigBowZoomEnabled");
				AutomaticZoom = Entry<bool>(type, "AutomaticBowZoom");
				ZoomFactor = Entry<float>(type, "BowZoomFactor");
				ZoomConstantTime = Entry<float>(type, "BowZoomConstantTime");
				MethodInfo methodInfo = AccessTools.Method(type, "IsBowZoomHeld", Type.EmptyTypes, (Type[])null);
				if (methodInfo == null || !methodInfo.IsStatic || methodInfo.ReturnType != typeof(bool))
				{
					throw new MissingMemberException(type.FullName, "static bool IsBowZoomHeld()");
				}
				IsZoomHeld = AccessTools.MethodDelegate<Func<bool>>(methodInfo, (object)null, true);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "TakeInput", Type.EmptyTypes, (Type[])null);
				if (methodInfo2 == null || methodInfo2.IsStatic || methodInfo2.ReturnType != typeof(bool))
				{
					throw new MissingMemberException("Player", "bool TakeInput()");
				}
				TakesInput = AccessTools.MethodDelegate<Func<Player, bool>>(methodInfo2, (object)null, true);
			}
			catch (Exception ex)
			{
				problem = ex.Message;
				return false;
			}
			problem = "";
			return true;
		}

		private static FieldInfo StaticField(Type main, string name, Type expected)
		{
			FieldInfo fieldInfo = AccessTools.Field(main, name);
			if (fieldInfo == null || !fieldInfo.IsStatic || fieldInfo.FieldType != expected)
			{
				throw new MissingMemberException(main.FullName, "static " + expected.Name + " " + name);
			}
			return fieldInfo;
		}

		private static FieldRef<T> Ref<T>(Type main, string name, Type? fieldType = null)
		{
			return AccessTools.StaticFieldRefAccess<T>(StaticField(main, name, fieldType ?? typeof(T)));
		}

		private static ConfigEntry<T> Entry<T>(Type main, string name)
		{
			return ((ConfigEntry<T>)StaticField(main, name, typeof(ConfigEntry<T>)).GetValue(null)) ?? throw new MissingMemberException(main.FullName, name + " is not bound yet");
		}
	}
	internal static class Patches
	{
		private static float zoomTime;

		private static bool ZoomingCrossbow(Player player)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Invalid comparison between Unknown and I4
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !BetterArcheryBridge.TakesInput(player))
			{
				return false;
			}
			if (!BetterArcheryBridge.ZoomEnabled.Value || BetterArcheryBridge.AutomaticZoom.Value)
			{
				return false;
			}
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			if (currentWeapon == null)
			{
				return false;
			}
			if (ZoomMath.IsCrossbow((int)currentWeapon.m_shared.m_itemType == 4, currentWeapon.m_shared.m_attack.m_requiresReload))
			{
				return BetterArcheryBridge.IsZoomHeld();
			}
			return false;
		}

		[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
		[HarmonyPostfix]
		[HarmonyPriority(-2)]
		private static void UpdateCrosshairPostfix(Player player)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (BetterArcheryBridge.BaseFov.Invoke() == 0f || !ZoomingCrossbow(player))
			{
				zoomTime = 0f;
				return;
			}
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			zoomTime += Time.deltaTime;
			BetterArcheryBridge.ZoomInTimer.Invoke() = zoomTime;
			BetterArcheryBridge.ZoomOutDelayTimer.Invoke() = 0f;
			BetterArcheryBridge.ZoomState.Invoke() = BetterArcheryBridge.ZoomingIn;
			float num = ZoomMath.ZoomFov(BetterArcheryBridge.BaseFov.Invoke(), BetterArcheryBridge.ZoomFactor.Value, BetterArcheryBridge.ZoomConstantTime.Value, BetterArcheryBridge.ZoomInTimer.Invoke(), ((Character)player).GetSkillFactor(currentWeapon.m_shared.m_skillType));
			BetterArcheryBridge.LastZoomFov.Invoke() = num;
			BetterArcheryBridge.NewZoomFov.Invoke() = num;
			GameCamera.instance.m_fov = num;
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		[HarmonyPrefix]
		private static void SetControlsPrefix(Player __instance, ref bool block, ref bool blockHold)
		{
			if ((block || blockHold) && __instance.GetDoodadController() == null && ZoomingCrossbow(__instance))
			{
				block = false;
				blockHold = false;
			}
		}
	}
	[BepInPlugin("helix.crossbowzoom", "CrossbowZoom", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "helix.crossbowzoom";

		public const string PluginName = "CrossbowZoom";

		public const string PluginVersion = "1.0.0";

		private void Awake()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (!BetterArcheryBridge.TryResolve(out string problem))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("BetterArchery " + BetterArcheryBridge.Version + ": " + problem + ". Crossbow zoom is off; nothing was patched."));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("BetterArchery " + BetterArcheryBridge.Version + ": all zoom members bound."));
				new Harmony("helix.crossbowzoom").PatchAll(typeof(Patches));
				LogPostfixOrder(((BaseUnityPlugin)this).Logger);
			}
		}

		private static void LogPostfixOrder(ManualLogSource log)
		{
			MethodBase methodBase = AccessTools.Method(typeof(Hud), "UpdateCrosshair", (Type[])null, (Type[])null);
			Patch[] postfixes = (Patch[])(((object)Harmony.GetPatchInfo(methodBase)?.Postfixes.ToArray()) ?? ((object)new Patch[0]));
			List<MethodInfo> sortedPatchMethods = PatchProcessor.GetSortedPatchMethods(methodBase, postfixes);
			string text = string.Join(" -> ", sortedPatchMethods.Select(delegate(MethodInfo m)
			{
				Patch val = postfixes.First((Patch x) => x.PatchMethod == m);
				return $"{m.DeclaringType?.FullName}.{m.Name} (priority {val.priority})";
			}));
			log.LogInfo((object)("Hud.UpdateCrosshair postfix order: " + text));
		}
	}
	internal static class ZoomMath
	{
		public static bool IsCrossbow(bool isBowItemType, bool requiresReload)
		{
			return isBowItemType && requiresReload;
		}

		public static float ZoomFov(float baseFov, float factor, float constantTime, float zoomInTimer, float skillFactor)
		{
			float num = 2f * (1f - skillFactor);
			if (num <= 0.1f)
			{
				num = 0.1f;
			}
			float t = ((constantTime > 0f) ? InverseLerp(0.05f, constantTime, zoomInTimer) : InverseLerp(0.05f, num, zoomInTimer));
			return Lerp(baseFov, baseFov / factor, t);
		}

		private static float Clamp01(float value)
		{
			if (!(value < 0f))
			{
				if (!(value > 1f))
				{
					return value;
				}
				return 1f;
			}
			return 0f;
		}

		private static float Lerp(float a, float b, float t)
		{
			return a + (b - a) * Clamp01(t);
		}

		private static float InverseLerp(float a, float b, float value)
		{
			if (a == b)
			{
				return 0f;
			}
			return Clamp01((value - a) / (b - a));
		}
	}
}