Decompiled source of ExtraRecoilData v1.3.3

ExtraRecoilData.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using System.Text.Json.Serialization;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using ExtraRecoilData.CustomRecoil;
using ExtraRecoilData.JSON;
using ExtraRecoilData.Patches;
using ExtraRecoilData.Utils;
using GTFO.API.JSON.Converters;
using GTFO.API.Utilities;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using MTFO.API;
using Microsoft.CodeAnalysis;
using Player;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ExtraRecoilData")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+77dc485c38981c602f3027ed08e8cd9f29f618b3")]
[assembly: AssemblyProduct("ExtraRecoilData")]
[assembly: AssemblyTitle("ExtraRecoilData")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace ExtraRecoilData
{
	[BepInPlugin("Dinorush.ExtraRecoilData", "ExtraRecoilData", "1.3.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string MODNAME = "ExtraRecoilData";

		public override void Load()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			ERDLogger.Log("Loading ExtraRecoilData");
			Harmony val = new Harmony("ExtraRecoilData");
			val.PatchAll(typeof(WeaponSetupPatches));
			val.PatchAll(typeof(RecoilPatches));
			ClassInjector.RegisterTypeInIl2Cpp<CustomRecoilComponent>();
			ERDLogger.Log("Loaded ExtraRecoilData");
		}
	}
}
namespace ExtraRecoilData.Utils
{
	internal static class ERDLogger
	{
		private static ManualLogSource logger = Logger.CreateLogSource("ExtraRecoilData");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
	internal static class FloatExtensions
	{
		public static float Map(this float orig, float fromMin, float fromMax, float toMin, float toMax)
		{
			if (fromMin == fromMax)
			{
				if (!(orig < fromMin))
				{
					return toMax;
				}
				return toMin;
			}
			orig = Mathf.Clamp(orig, fromMin, fromMax);
			return (orig - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
		}
	}
}
namespace ExtraRecoilData.Patches
{
	internal static class RecoilPatches
	{
		private static BulletWeapon? cachedWeapon;

		private static CustomRecoilComponent? cachedManager;

		internal static void RefreshCache(BulletWeapon weapon)
		{
			if ((Object)(object)cachedWeapon != (Object)null && ((Object)weapon).GetInstanceID() == ((Object)cachedWeapon).GetInstanceID())
			{
				cachedManager = ((Component)cachedWeapon).GetComponent<CustomRecoilComponent>();
			}
		}

		private static CustomRecoilComponent? GetCustomRecoilManager(BulletWeapon? newWeapon = null)
		{
			if ((Object)(object)newWeapon == (Object)null)
			{
				return cachedManager;
			}
			PlayerAgent owner = ((Item)newWeapon).Owner;
			if (owner == null || !((Agent)owner).IsLocallyOwned)
			{
				return null;
			}
			if ((Object)(object)cachedWeapon == (Object)null || ((Object)newWeapon).GetInstanceID() != ((Object)cachedWeapon).GetInstanceID())
			{
				cachedWeapon = newWeapon;
				cachedManager = ((Component)newWeapon).GetComponent<CustomRecoilComponent>();
			}
			return cachedManager;
		}

		[HarmonyPatch(typeof(BulletWeapon), "OnWield")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void UpdateCurrentWeapon(BulletWeapon __instance)
		{
			GetCustomRecoilManager(__instance);
		}

		[HarmonyPatch(typeof(BulletWeapon), "OnUnWield")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void RemoveCurrentWeapon(BulletWeapon __instance)
		{
			PlayerAgent owner = ((Item)__instance).Owner;
			if (owner == null || ((Agent)owner).IsLocallyOwned)
			{
				cachedWeapon = null;
				cachedManager = null;
			}
		}

		[HarmonyPatch(typeof(BulletWeaponArchetype), "PostFireCheck")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void UpdateCustomRecoil(BulletWeaponArchetype __instance)
		{
			CustomRecoilComponent customRecoilManager = GetCustomRecoilManager(__instance.m_weapon);
			if (!((Object)(object)customRecoilManager == (Object)null))
			{
				customRecoilManager.FireTriggered(Math.Max(0f, Math.Max(__instance.m_nextShotTimer, __instance.m_nextBurstTimer)));
			}
		}

		[HarmonyPatch(typeof(FPS_RecoilSystem), "ApplyRecoil")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void CustomApplyRecoilAfter(FPS_RecoilSystem __instance, bool resetSimilarity, RecoilDataBlock recoilData)
		{
			//IL_0014: 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)
			//IL_0020: 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_0030: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cachedManager == (Object)null))
			{
				Vector2 modifiedRecoil = cachedManager.GetModifiedRecoil(__instance.recoilDir);
				Vector2 currentRecoilForce = __instance.currentRecoilForce;
				currentRecoilForce.x += (__instance.recoilDir.x - modifiedRecoil.x) * (1f - recoilData.worldToViewSpaceBlendVertical);
				currentRecoilForce.y += (__instance.recoilDir.y - modifiedRecoil.y) * (1f - recoilData.worldToViewSpaceBlendHorizontal);
				Vector2 currentRecoilForceVP = __instance.currentRecoilForceVP;
				currentRecoilForceVP.x += (__instance.recoilDir.x - modifiedRecoil.x) * recoilData.worldToViewSpaceBlendVertical;
				currentRecoilForceVP.y += (__instance.recoilDir.y - modifiedRecoil.y) * recoilData.worldToViewSpaceBlendHorizontal;
				__instance.recoilDir = modifiedRecoil;
				__instance.currentRecoilForce = currentRecoilForce;
				__instance.currentRecoilForceVP = currentRecoilForceVP;
			}
		}
	}
	internal static class WeaponSetupPatches
	{
		[HarmonyPatch(typeof(BulletWeaponArchetype), "SetOwner")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void SetupCallback(BulletWeaponArchetype __instance, PlayerAgent owner)
		{
			if (!((Object)(object)owner == (Object)null))
			{
				CustomRecoilData customRecoilData = CustomRecoilManager.Current.GetCustomRecoilData(((GameDataBlockBase<ArchetypeDataBlock>)(object)__instance.m_archetypeData).persistentID);
				if (customRecoilData != null && !((Object)(object)((Component)__instance.m_weapon).gameObject.GetComponent<CustomRecoilComponent>() != (Object)null))
				{
					((Component)__instance.m_weapon).gameObject.AddComponent<CustomRecoilComponent>().Data = customRecoilData;
				}
			}
		}
	}
}
namespace ExtraRecoilData.JSON
{
	public static class ERDJson
	{
		private static readonly JsonSerializerOptions _setting;

		static ERDJson()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			_setting = new JsonSerializerOptions
			{
				ReadCommentHandling = JsonCommentHandling.Skip,
				IncludeFields = true,
				PropertyNameCaseInsensitive = true,
				WriteIndented = true,
				IgnoreReadOnlyProperties = true
			};
			_setting.Converters.Add(new JsonStringEnumConverter());
			_setting.Converters.Add(new MinMaxConverter());
			if (MTFOPartialDataUtil.IsLoaded)
			{
				_setting.Converters.Add(MTFOPartialDataUtil.PersistentIDConverter);
				_setting.Converters.Add(MTFOPartialDataUtil.LocalizedTextConverter);
				ERDLogger.Log("PartialData support found!");
			}
			else
			{
				_setting.Converters.Add((JsonConverter)new LocalizedTextConverter());
			}
		}

		public static T? Deserialize<T>(string json)
		{
			return JsonSerializer.Deserialize<T>(json, _setting);
		}

		public static object? Deserialize(Type type, string json)
		{
			return JsonSerializer.Deserialize(json, type, _setting);
		}

		public static string Serialize<T>(T value)
		{
			return JsonSerializer.Serialize(value, _setting);
		}
	}
	public sealed class MinMaxConverter : JsonConverter<MinMaxValue>
	{
		public override MinMaxValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			if (reader.TokenType != JsonTokenType.StartObject)
			{
				throw new JsonException("Missing { for MinMaxValue object");
			}
			MinMaxValue val = new MinMaxValue();
			while (reader.Read())
			{
				if (reader.TokenType == JsonTokenType.EndObject)
				{
					return val;
				}
				if (reader.TokenType != JsonTokenType.PropertyName)
				{
					throw new JsonException("Expected PropertyName token");
				}
				string? @string = reader.GetString();
				reader.Read();
				string text = @string.ToLowerInvariant();
				if (!(text == "min"))
				{
					if (!(text == "max"))
					{
						throw new JsonException("Expected Min or Max property");
					}
					val.Max = reader.GetSingle();
				}
				else
				{
					val.Min = reader.GetSingle();
				}
			}
			throw new JsonException("Expected EndObject token");
		}

		public override void Write(Utf8JsonWriter writer, MinMaxValue value, JsonSerializerOptions options)
		{
			writer.WriteStartObject();
			writer.WritePropertyName("Min");
			writer.WriteNumberValue(value.Min);
			writer.WritePropertyName("Max");
			writer.WriteNumberValue(value.Max);
			writer.WriteEndObject();
		}
	}
	internal static class MTFOPartialDataUtil
	{
		public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks";

		public static JsonConverter PersistentIDConverter { get; private set; }

		public static JsonConverter LocalizedTextConverter { get; private set; }

		public static bool IsLoaded { get; private set; }

		public static bool Initialized { get; private set; }

		public static string PartialDataPath { get; private set; }

		public static string ConfigPath { get; private set; }

		static MTFOPartialDataUtil()
		{
			PersistentIDConverter = null;
			LocalizedTextConverter = null;
			IsLoaded = false;
			Initialized = false;
			PartialDataPath = string.Empty;
			ConfigPath = string.Empty;
			if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value))
			{
				return;
			}
			try
			{
				Assembly obj = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null;
				if ((object)obj == null)
				{
					throw new Exception("Assembly is Missing!");
				}
				Type[] types = obj.GetTypes();
				Type type = types.First((Type t) => t.Name == "PersistentIDConverter");
				if ((object)type == null)
				{
					throw new Exception("Unable to Find PersistentIDConverter Class");
				}
				Type type2 = types.First((Type t) => t.Name == "PartialDataManager");
				if ((object)type2 == null)
				{
					throw new Exception("Unable to Find PartialDataManager Class");
				}
				Type type3 = types.First((Type t) => t.Name == "LocalizedTextConverter") ?? throw new Exception("Unable to Find LocalizedTextConverter Class");
				PropertyInfo property = type2.GetProperty("Initialized", BindingFlags.Static | BindingFlags.Public);
				PropertyInfo property2 = type2.GetProperty("PartialDataPath", BindingFlags.Static | BindingFlags.Public);
				PropertyInfo? property3 = type2.GetProperty("ConfigPath", BindingFlags.Static | BindingFlags.Public);
				if ((object)property == null)
				{
					throw new Exception("Unable to Find Property: Initialized");
				}
				if ((object)property2 == null)
				{
					throw new Exception("Unable to Find Property: PartialDataPath");
				}
				if ((object)property3 == null)
				{
					throw new Exception("Unable to Find Field: ConfigPath");
				}
				Initialized = (bool)property.GetValue(null);
				PartialDataPath = (string)property2.GetValue(null);
				ConfigPath = (string)property3.GetValue(null);
				PersistentIDConverter = (JsonConverter)Activator.CreateInstance(type);
				LocalizedTextConverter = (JsonConverter)Activator.CreateInstance(type3);
				IsLoaded = true;
			}
			catch (Exception value2)
			{
				ERDLogger.Error($"Exception thrown while reading data from MTFO_Extension_PartialData:\n{value2}");
			}
		}
	}
	internal static class MTFOUtil
	{
		public const string PLUGIN_GUID = "com.dak.MTFO";

		public const BindingFlags PUBLIC_STATIC = BindingFlags.Static | BindingFlags.Public;

		public static string GameDataPath { get; private set; }

		public static string CustomPath { get; private set; }

		public static bool HasCustomContent { get; private set; }

		public static bool IsLoaded { get; private set; }

		static MTFOUtil()
		{
			GameDataPath = string.Empty;
			CustomPath = string.Empty;
			HasCustomContent = false;
			IsLoaded = false;
			if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("com.dak.MTFO", out var value))
			{
				return;
			}
			try
			{
				Assembly obj = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null;
				if ((object)obj == null)
				{
					throw new Exception("Assembly is Missing!");
				}
				Type obj2 = obj.GetTypes().First((Type t) => t.Name == "ConfigManager") ?? throw new Exception("Unable to Find ConfigManager Class");
				FieldInfo field = obj2.GetField("GameDataPath", BindingFlags.Static | BindingFlags.Public);
				FieldInfo field2 = obj2.GetField("CustomPath", BindingFlags.Static | BindingFlags.Public);
				FieldInfo? field3 = obj2.GetField("HasCustomContent", BindingFlags.Static | BindingFlags.Public);
				if ((object)field == null)
				{
					throw new Exception("Unable to Find Field: GameDataPath");
				}
				if ((object)field2 == null)
				{
					throw new Exception("Unable to Find Field: CustomPath");
				}
				if ((object)field3 == null)
				{
					throw new Exception("Unable to Find Field: HasCustomContent");
				}
				GameDataPath = (string)field.GetValue(null);
				CustomPath = (string)field2.GetValue(null);
				HasCustomContent = (bool)field3.GetValue(null);
				IsLoaded = true;
			}
			catch (Exception value2)
			{
				ERDLogger.Log($"Exception thrown while reading path from DataDumper (MTFO): \n{value2}");
			}
		}
	}
}
namespace ExtraRecoilData.CustomRecoil
{
	public class CustomRecoilComponent : MonoBehaviour
	{
		protected CustomRecoilData data = new CustomRecoilData();

		protected List<Vector2> recoilPattern = new List<Vector2>();

		protected int recoilPatternIndex;

		protected List<Vector2> recoilPatternFirst = new List<Vector2>();

		protected int recoilPatternFirstIndex;

		protected float recoilScaleProgress;

		protected float lastUpdateTime;

		protected float nextShotTime;

		public CustomRecoilData Data
		{
			get
			{
				return data;
			}
			set
			{
				data = value;
				data.RecoilScaleCap = ((data.RecoilScaleCap >= 0f) ? data.RecoilScaleCap : 0f);
				data.RecoilScaleThreshold = Mathf.Clamp(data.RecoilScaleThreshold, 0f, data.RecoilScaleCap);
				SetRecoilPattern(ref recoilPattern, data.RecoilPattern);
				SetRecoilPattern(ref recoilPatternFirst, data.RecoilPatternFirst);
			}
		}

		public CustomRecoilComponent(IntPtr value)
			: base(value)
		{
		}

		protected static void SetRecoilPattern(ref List<Vector2> localPattern, List<float> pattern)
		{
			localPattern.Clear();
			if (pattern.Any((float val) => Math.Abs(val) > 1f))
			{
				localPattern = CreatePatternFromPolar(pattern);
			}
			else
			{
				localPattern = CreatePatternFromEuclidean(pattern);
			}
		}

		protected static List<Vector2> CreatePatternFromPolar(List<float> pattern)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2> list = new List<Vector2>(pattern.Count);
			for (int i = 0; i < pattern.Count; i++)
			{
				float num = (0f - pattern[i] + 90f) * ((float)Math.PI / 180f);
				list.Add(new Vector2((float)Math.Sin(num), (float)(0.0 - Math.Cos(num))));
			}
			return list;
		}

		protected static List<Vector2> CreatePatternFromEuclidean(List<float> pattern)
		{
			//IL_0048: 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)
			//IL_0056: 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)
			List<Vector2> list = new List<Vector2>(pattern.Count / 2);
			for (int i = 0; i < pattern.Count - 1; i += 2)
			{
				Vector2 item = (Vector2)((pattern[i] != 0f || pattern[i + 1] != 0f) ? new Vector2(pattern[i + 1], 0f - pattern[i]) : Vector2.right);
				((Vector2)(ref item)).Normalize();
				list.Add(item);
			}
			return list;
		}

		protected void UpdateToPresent()
		{
			if (lastUpdateTime != Clock.Time)
			{
				float num = Clock.Time - nextShotTime;
				float num2 = Clock.Time - lastUpdateTime;
				if (num > data.RecoilScaleDecayDelay)
				{
					float num3 = num2 - Math.Max(0f, data.RecoilScaleDecayDelay + nextShotTime - lastUpdateTime);
					recoilScaleProgress = Math.Max(0f, Math.Min(data.RecoilScaleCap, recoilScaleProgress - data.RecoilScaleDecay * num3));
				}
				if (num > data.RecoilPatternResetDelay)
				{
					recoilPatternIndex = 0;
					recoilPatternFirstIndex = 0;
				}
				lastUpdateTime = Clock.Time;
			}
		}

		public Vector2 GetModifiedRecoil(Vector2 recoilDir)
		{
			//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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_010d: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_00e5: 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)
			//IL_00f3: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			UpdateToPresent();
			float num = recoilScaleProgress.Map(data.RecoilScaleThreshold, data.RecoilScaleCap, data.RecoilScaleMin, data.RecoilScaleMax);
			float num2 = recoilScaleProgress.Map(data.RecoilScaleThreshold, data.RecoilScaleCap, data.RecoilPatternScaleMin, data.RecoilPatternScaleMax);
			Vector2 val = Vector2.right;
			if (recoilPatternFirstIndex < recoilPatternFirst.Count)
			{
				val = recoilPatternFirst[recoilPatternFirstIndex];
			}
			else if (recoilPattern.Count > 0)
			{
				val = recoilPattern[recoilPatternIndex];
			}
			if (data.RecoilPatternAlign == RecoilPatternAlign.ALIGN)
			{
				((Vector2)(ref recoilDir)).Set(recoilDir.x * val.x - recoilDir.y * val.y, recoilDir.y * val.x + recoilDir.x * val.y);
			}
			return recoilDir * num + val * data.RecoilPatternPower.GetRandom() * num2;
		}

		public void FireTriggered(float newShotTime)
		{
			UpdateToPresent();
			nextShotTime = (data.RecoilDelayStartOnFire ? Clock.Time : newShotTime);
			recoilScaleProgress = Math.Min(recoilScaleProgress + 1f, data.RecoilScaleCap);
			if (recoilPatternFirstIndex < recoilPatternFirst.Count)
			{
				recoilPatternFirstIndex++;
			}
			else if (recoilPattern.Count > 0)
			{
				recoilPatternIndex = (recoilPatternIndex + 1) % recoilPattern.Count;
			}
		}
	}
	public class CustomRecoilData
	{
		public bool RecoilDelayStartOnFire;

		public uint ArchetypeID { get; set; }

		public string Name { get; set; } = string.Empty;


		public float RecoilScaleCap { get; set; } = 1f;


		public float RecoilScaleThreshold { get; set; }

		public float RecoilScaleDecay { get; set; } = 1f;


		public float RecoilScaleDecayDelay { get; set; } = 0.016f;


		public float RecoilScaleMin { get; set; } = 1f;


		public float RecoilScaleMax { get; set; } = 1f;


		public float RecoilPatternScaleMin { get; set; } = 1f;


		public float RecoilPatternScaleMax { get; set; } = 1f;


		public List<float> RecoilPattern { get; set; } = new List<float>();


		public List<float> RecoilPatternFirst { get; set; } = new List<float>();


		public RecoilPatternAlign RecoilPatternAlign { get; set; }

		public MinMaxValue RecoilPatternPower { get; set; } = new MinMaxValue
		{
			Min = 0f,
			Max = 0f
		};


		public float RecoilPatternResetDelay { get; set; } = 0.016f;

	}
	public class CustomRecoilManager
	{
		private readonly Dictionary<uint, CustomRecoilData> customData = new Dictionary<uint, CustomRecoilData>();

		private readonly LiveEditListener liveEditListener;

		public static CustomRecoilManager Current { get; private set; }

		public string DEFINITION_PATH { get; private set; }

		public override string ToString()
		{
			return "Printing manager: " + customData.ToString();
		}

		protected virtual void AddCustomRecoilData(CustomRecoilData? data)
		{
			if (data != null)
			{
				if (customData.ContainsKey(data.ArchetypeID))
				{
					ERDLogger.Warning("Replaced custom recoil for ArchetypeID " + data.ArchetypeID);
				}
				customData[data.ArchetypeID] = data;
			}
		}

		protected virtual void FileChanged(LiveEditEventArgs e)
		{
			ERDLogger.Warning("LiveEdit File Changed: " + e.FullPath);
			LiveEdit.TryReadFileContent(e.FullPath, (Action<string>)delegate(string content)
			{
				List<CustomRecoilData> list = ERDJson.Deserialize<List<CustomRecoilData>>(content);
				if (list == null)
				{
					return;
				}
				foreach (CustomRecoilData item in list)
				{
					AddCustomRecoilData(item);
				}
			});
		}

		public CustomRecoilData? GetCustomRecoilData(uint ArchetypeID)
		{
			if (!customData.ContainsKey(ArchetypeID))
			{
				return null;
			}
			return customData[ArchetypeID];
		}

		private CustomRecoilManager()
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			DEFINITION_PATH = Path.Combine(MTFOPathAPI.CustomPath, "ExtraRecoilData");
			if (!Directory.Exists(DEFINITION_PATH))
			{
				Directory.CreateDirectory(DEFINITION_PATH);
				StreamWriter streamWriter = File.CreateText(Path.Combine(DEFINITION_PATH, "Template.json"));
				streamWriter.WriteLine(ERDJson.Serialize(new List<CustomRecoilData>
				{
					new CustomRecoilData()
				}));
				streamWriter.Flush();
				streamWriter.Close();
			}
			foreach (string item in Directory.EnumerateFiles(DEFINITION_PATH, "*.json", SearchOption.AllDirectories))
			{
				List<CustomRecoilData> list = ERDJson.Deserialize<List<CustomRecoilData>>(File.ReadAllText(item));
				if (list == null)
				{
					continue;
				}
				foreach (CustomRecoilData item2 in list)
				{
					AddCustomRecoilData(item2);
				}
			}
			liveEditListener = LiveEdit.CreateListener(DEFINITION_PATH, "*.json", true);
			liveEditListener.FileChanged += new LiveEditEventHandler(FileChanged);
		}

		static CustomRecoilManager()
		{
			Current = new CustomRecoilManager();
		}
	}
	public enum RecoilPatternAlign
	{
		ALIGN,
		ABSOLUTE
	}
}
namespace ExtraRecoilData.API
{
	public static class ChangeAPI
	{
		public static void ChangeERDComponent(uint archetypeID, BulletWeapon weapon)
		{
			CustomRecoilComponent component = ((Component)weapon).GetComponent<CustomRecoilComponent>();
			CustomRecoilData customRecoilData = CustomRecoilManager.Current.GetCustomRecoilData(archetypeID);
			if ((Object)(object)component != (Object)null)
			{
				component.Data = customRecoilData ?? new CustomRecoilData();
			}
			else if (customRecoilData != null)
			{
				component = ((Component)weapon).gameObject.AddComponent<CustomRecoilComponent>();
				component.Data = customRecoilData;
			}
			RecoilPatches.RefreshCache(weapon);
		}
	}
}