Decompiled source of GunTweaker v1.1.4

Mods/GunTweaker.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using GunTweaker;
using HarmonyLib;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSystem.Collections.Generic;
using LabFusion.SDK.Gamemodes;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Tomlet;
using Tomlet.Models;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("GunTweaker")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany(null)]
[assembly: AssemblyProduct("GunTweaker")]
[assembly: AssemblyCopyright("Created by Adi")]
[assembly: AssemblyTrademark(null)]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.1.4")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: MelonInfo(typeof(global::GunTweaker.GunTweaker), "GunTweaker", "1.1.4", "Adi", null)]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: MelonGame(null, null)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.1.4.0")]
namespace GunTweaker;

public static class FiremodeGarbage
{
	public enum Firemode
	{
		Automatic,
		SemiAutomatic,
		BoltAction,
		Burst,
		BinaryTrigger
	}

	[HarmonyPatch(typeof(Gun), "OnFire")]
	public static class GunPatch4000
	{
		public static void Prefix(Gun __instance)
		{
			if (GunTweaker.TryGetGunInfo(__instance, out var info))
			{
				info.ApplyTweaks(__instance);
			}
		}

		public static void Postfix(Gun __instance)
		{
			if (!GunTweaker.TryGetGunInfo(__instance, out var info) || coroutines.ContainsKey(((Object)__instance).GetInstanceID()))
			{
				return;
			}
			if (info.AutoEject != null && (bool)info.AutoEject && info.SlideLockedOnEmpty != null && !info.SlideLockedOnEmpty && __instance.HasMagazine())
			{
				MagazineState magState = __instance._magState;
				if (magState != null && magState.AmmoCount == 0)
				{
					AmmoSocket componentInChildren = ((Component)__instance).GetComponentInChildren<AmmoSocket>();
					if (componentInChildren != null)
					{
						componentInChildren.EjectMagazine();
					}
					return;
				}
			}
			if ((Firemode)info.FireMode == Firemode.Burst)
			{
				MelonCoroutines.Start(Burst(__instance, info));
			}
			if ((Firemode)info.FireMode == Firemode.BinaryTrigger)
			{
				MelonCoroutines.Start(BinaryTrigger(__instance));
			}
		}
	}

	[HarmonyPatch(typeof(Gun), "Fire")]
	public static class GunPatch8000
	{
		public static bool Prefix(Gun __instance)
		{
			GunTweaker.isFiring = true;
			int instanceID = ((Object)__instance).GetInstanceID();
			if (!coroutines.TryGetValue(instanceID, out var value))
			{
				return true;
			}
			return value;
		}

		public static void Postfix()
		{
			GunTweaker.isFiring = false;
		}
	}

	[HarmonyPatch(typeof(Gun), "PullCartridge")]
	public static class InfiniteAmmoPatch
	{
		public static void Postfix(Gun __instance)
		{
			if (GunTweaker.TryGetGunInfo(__instance, out var info) && (bool)info.InfiniteAmmo)
			{
				MagazineState magState = __instance._magState;
				if (magState != null)
				{
					magState.Refill();
				}
			}
		}
	}

	public static Dictionary<int, bool> coroutines = new Dictionary<int, bool>();

	public static FireMode GTFM2BLFM(this Firemode fm)
	{
		//IL_0015: 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_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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)
		return (FireMode)(fm switch
		{
			Firemode.Automatic => 2, 
			Firemode.SemiAutomatic => 1, 
			Firemode.BoltAction => 0, 
			_ => 1, 
		});
	}

	public static void SetFiremode(this Gun gun, Firemode fm)
	{
		//IL_000c: 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_0010: 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)
		gun.fireMode = (FireMode)(fm switch
		{
			Firemode.Automatic => 2, 
			Firemode.BoltAction => 0, 
			_ => 1, 
		});
	}

	public static IEnumerator Burst(Gun gun, GunInfo info)
	{
		int uuid = ((Object)gun).GetInstanceID();
		coroutines.Add(uuid, value: false);
		for (int i = 0; i < (int)info.BurstSize - 1; i++)
		{
			float timer = Time.time + 1f / gun.roundsPerSecond;
			while (Time.time < timer)
			{
				yield return null;
			}
			yield return (object)new WaitForFixedUpdate();
			if ((Object)(object)gun.chamberedCartridge == (Object)null && (!gun.HasMagazine() || !gun._hasMagState || gun.AmmoCount() == 0))
			{
				break;
			}
			gun.fireMode = (FireMode)2;
			coroutines[uuid] = true;
			gun.Fire();
			coroutines[uuid] = false;
			gun.fireMode = (FireMode)1;
		}
		gun.SetFiremode(info.FireMode);
		coroutines.Remove(uuid);
	}

	private static IEnumerator BinaryTrigger(Gun gun)
	{
		int uuid = ((Object)gun).GetInstanceID();
		coroutines.Add(uuid, value: false);
		float timer = Time.time + 1.1f / gun.roundsPerSecond;
		while (Time.time < timer || gun.isTriggerPulled)
		{
			yield return null;
		}
		gun.fireMode = (FireMode)2;
		coroutines[uuid] = true;
		gun.Fire();
		coroutines[uuid] = false;
		gun.fireMode = (FireMode)1;
		yield return (object)new WaitForEndOfFrame();
		coroutines.Remove(uuid);
	}
}
public class GunInfo
{
	public class OGGunInfo
	{
		public float FireRate { get; private set; }

		public FireMode FireMode { get; private set; }

		public FiremodeGarbage.Firemode FireModeGT { get; private set; }

		public bool SlideLockedOnEmpty { get; private set; }

		public bool SlideReleaseOnCollision { get; private set; }

		public bool MagEjectOnEmpty { get; private set; }

		public OGGunInfo(Gun gun)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected I4, but got Unknown
			FireRate = gun.roundsPerMinute;
			FireMode = gun.fireMode;
			SlideReleaseOnCollision = gun.isSlideReleaseOnCollision;
			SlideLockedOnEmpty = gun.isSlideLockedOnEmpty;
			MagEjectOnEmpty = gun.isMagEjectOnEmpty;
			FireMode fireMode = gun.fireMode;
			FireModeGT = (int)fireMode switch
			{
				2 => FiremodeGarbage.Firemode.Automatic, 
				1 => FiremodeGarbage.Firemode.SemiAutomatic, 
				0 => FiremodeGarbage.Firemode.BoltAction, 
				_ => FiremodeGarbage.Firemode.SemiAutomatic, 
			};
		}
	}

	public enum AmmoTypes
	{
		Normal,
		Explosive
	}

	public static Dictionary<string, Preferences.GunPref> gunPrefs = new Dictionary<string, Preferences.GunPref>();

	public Dictionary<string, float> rbWeights = new Dictionary<string, float>();

	public float FireRate => Preferences.GlobalFirerateMultiplier.Value * (float)FireRateMult * OGInfo.FireRate;

	public string Name { get; set; }

	public float Damage => OGProjectileData.DamageMultiplier * Preferences.GlobalDamageMultiplier.Value * (float)DamageMult;

	public bool IsShotgun { get; set; }

	public bool IsPumpShotgun { get; private set; }

	public bool IsModded { get; set; }

	public bool WeirdGunTriggerShit { get; set; }

	public bool HasInternalMagazine { get; private set; }

	public bool HasBeenTweaked
	{
		get
		{
			if ((int)MagCapacity <= OGProjectileData.DefaultMagCapacity && !((float)FireRateMult > 1.01f) && !((float)DamageMult > 1.01f) && !((float)VelocityMult > 1.01f) && !((float)MassMult > 1.01f) && !InfiniteAmmo && ((FiremodeGarbage.Firemode)FireMode == OGInfo.FireModeGT || (FiremodeGarbage.Firemode)FireMode == FiremodeGarbage.Firemode.BoltAction) && (int)ProjCount <= OGProjectileData.Count)
			{
				return (float)RecoilMult <= 1.01f;
			}
			return true;
		}
	}

	public AmmoInfo OGProjectileData { get; private set; }

	public MagazineData Mag { get; set; }

	public CartridgeData DefaultCart { get; set; }

	public int CurrentProfile { get; set; }

	public GunPref<float> FireRateMult { get; set; }

	public GunPref<float> DamageMult { get; set; }

	public GunPref<float> MassMult { get; set; }

	public GunPref<float> VelocityMult { get; set; }

	public GunPref<int> MagCapacity { get; set; }

	public GunPref<FiremodeGarbage.Firemode> FireMode { get; set; }

	public GunPref<int> BurstSize { get; set; }

	public GunPref<bool> SlideReleaseOnCollision { get; set; }

	public GunPref<bool> InfiniteAmmo { get; set; }

	public GunPref<bool> PseudoShotgun { get; set; }

	public GunPref<int> ProjCount { get; set; }

	public GunPref<float> Spread { get; set; }

	public GunPref<bool> SlideLockedOnEmpty { get; set; }

	public GunPref<bool> MagEject { get; set; }

	public GunPref<bool> AutoEject { get; set; }

	public GunPref<bool> ScaleRecoil { get; set; }

	public GunPref<float> RecoilMult { get; set; }

	public GunPref<float> WeightMult { get; set; }

	public OGGunInfo OGInfo { get; set; }

	public HashSet<Gun> Instances { get; set; } = new HashSet<Gun>();


	public Dictionary<GunTrigger, FireMode> GunTriggers { get; set; }

	public HashSet<int> InstanceIds { get; set; } = new HashSet<int>();


	public GunInfo(Gun gun, string pooleeName)
	{
		Name = pooleeName;
		OGProjectileData = new AmmoInfo(gun.defaultCartridge.projectile, gun.internalMagazine ?? gun.defaultMagazine);
		Mag = gun.internalMagazine ?? gun.defaultMagazine;
		DefaultCart = gun.defaultCartridge;
		OGInfo = new OGGunInfo(gun);
		IsShotgun = ((Crate)((SpawnEvents)gun)._poolee.SpawnableCrate)._tags.Contains("Shotgun");
		IsPumpShotgun = (Object)(object)((Component)gun).GetComponentInChildren<PumpShotgunVirtualController>() != (Object)null;
		IsModded = !((Crate)((SpawnEvents)gun)._poolee.SpawnableCrate)._pallet.Internal;
		WeirdGunTriggerShit = ((Component)gun).GetComponentsInChildren<GunTrigger>().Count > 1;
		HasInternalMagazine = (Object)(object)gun.internalMagazine != (Object)null;
		foreach (Rigidbody componentsInChild in ((Component)((Component)gun).transform.root).GetComponentsInChildren<Rigidbody>())
		{
			string cleanObjectName = HelperMethods.GetCleanObjectName(((Object)componentsInChild).name);
			float mass = componentsInChild.mass;
			if (!rbWeights.ContainsKey(cleanObjectName))
			{
				rbWeights.Add(cleanObjectName, mass);
			}
		}
		CreatePrefs();
	}

	public void CreatePrefs()
	{
		//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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Expected I4, but got Unknown
		Preferences.GunPref value = null;
		gunPrefs.TryGetValue(Name, out value);
		int[] value2 = ((value == null) ? null : new int[1] { value.CurrentProfile });
		CurrentProfile = new GunPref<int>(this, "CurrentProfile", 1, value2, multipleProfiles: false);
		FireRateMult = new GunPref<float>(this, "FirerateMultiplier", 1f, value?.FirerateMultiplier);
		DamageMult = new GunPref<float>(this, "DamageMultiplier", 1f, value?.DamageMultiplier);
		MassMult = new GunPref<float>(this, "ProjectileMassMultiplier", 1f, value?.ProjectileMassMultiplier);
		VelocityMult = new GunPref<float>(this, "ProjectileVelocityMultiplier", 1f, value?.ProjectileVelocityMultiplier);
		BurstSize = new GunPref<int>(this, "RoundsPerBurst", 3, value?.RoundsPerBurst);
		FireMode fireMode = OGInfo.FireMode;
		FireMode = new GunPref<FiremodeGarbage.Firemode>(this, "Firemode", (int)fireMode switch
		{
			2 => FiremodeGarbage.Firemode.Automatic, 
			1 => FiremodeGarbage.Firemode.SemiAutomatic, 
			0 => FiremodeGarbage.Firemode.BoltAction, 
			_ => FiremodeGarbage.Firemode.SemiAutomatic, 
		}, value?.Firemode);
		MagCapacity = new GunPref<int>(this, "MagazineCapacity", OGProjectileData.DefaultMagCapacity, value?.MagazineCapacity);
		InfiniteAmmo = new GunPref<bool>(this, "InfiniteAmmo", defaultVal: false, value?.InfiniteAmmo);
		if (!IsPumpShotgun)
		{
			SlideLockedOnEmpty = new GunPref<bool>(this, "SlideLock", OGInfo.SlideLockedOnEmpty, value?.SlideLock);
			SlideReleaseOnCollision = new GunPref<bool>(this, "SlideReleaseOnCollision", OGInfo.SlideReleaseOnCollision, value?.SlideReleaseOnCollision);
		}
		if (!HasInternalMagazine)
		{
			MagEject = new GunPref<bool>(this, "MagEject", !OGInfo.MagEjectOnEmpty, value?.MagEject);
			AutoEject = new GunPref<bool>(this, "AutoEject", OGInfo.MagEjectOnEmpty, value?.AutoEject);
		}
		if (!IsShotgun)
		{
			PseudoShotgun = new GunPref<bool>(this, "PseudoShotgun", defaultVal: false, value?.PseudoShotgun);
		}
		ProjCount = new GunPref<int>(this, "ProjectileCount", OGProjectileData.Count, value?.ProjectileCount);
		Spread = new GunPref<float>(this, "Spread", OGProjectileData.Angle, value?.Spread);
		RecoilMult = new GunPref<float>(this, "RecoilMult", 1f, value?.RecoilMult);
		WeightMult = new GunPref<float>(this, "WeightMult", 1f, value?.WeightMult);
		ScaleRecoil = new GunPref<bool>(this, "ScaleRecoil", defaultVal: false, value?.ScaleRecoil);
	}

	public void Reset(bool allProfiles = false)
	{
		FireRateMult?.Reset(allProfiles);
		DamageMult?.Reset(allProfiles);
		MassMult?.Reset(allProfiles);
		VelocityMult?.Reset(allProfiles);
		RecoilMult?.Reset(allProfiles);
		BurstSize?.Reset(allProfiles);
		InfiniteAmmo?.Reset(allProfiles);
		WeightMult?.Reset(allProfiles);
		if (!IsShotgun)
		{
			PseudoShotgun?.Reset(allProfiles);
		}
		Spread?.Reset(allProfiles);
		ProjCount?.Reset(allProfiles);
		if (!IsPumpShotgun)
		{
			SlideLockedOnEmpty?.Reset(allProfiles);
			SlideReleaseOnCollision?.Reset(allProfiles);
		}
		if (!HasInternalMagazine)
		{
			MagEject?.Reset(allProfiles);
			AutoEject?.Reset(allProfiles);
		}
		FireMode?.Reset(allProfiles);
		MagCapacity?.Reset(allProfiles);
		ScaleRecoil?.Reset(allProfiles);
	}

	public static bool CheckFusion()
	{
		if (Gamemode.IsGamemodeRunning)
		{
			if (!Gamemode.ActiveGamemode.DisableSpawnGun)
			{
				return Gamemode.ActiveGamemode.DisableDevTools;
			}
			return true;
		}
		return false;
	}

	public void ApplyTweaks(Gun spawnedGun = null)
	{
		if (GunTweaker.fusionInstalled && CheckFusion())
		{
			return;
		}
		foreach (Gun instance in Instances)
		{
			if ((Object)(object)spawnedGun != (Object)null && (Object)(object)instance != (Object)(object)spawnedGun)
			{
				continue;
			}
			Extensions.SetRpm(instance, FireRate);
			instance.SetFiremode(FireMode);
			instance.defaultCartridge.projectile.damageMultiplier = Damage;
			instance.defaultCartridge.projectile.mass = OGProjectileData.Mass * (float)MassMult * Preferences.GlobalMassMultiplier.Value;
			instance.defaultCartridge.projectile.startVelocity = OGProjectileData.StartVelocity * (float)VelocityMult * Preferences.GlobalVelocityMultiplier.Value;
			instance.defaultCartridge.projectile.angle = ((IsShotgun || (bool)PseudoShotgun) ? ((float)Spread) : 0f);
			instance.defaultCartridge.projectile.count = ((!IsShotgun && !PseudoShotgun) ? 1 : ((int)ProjCount));
			instance.defaultCartridge.projectile.emissionType = (EmissionType)(((int)ProjCount != 1 || (float)Spread > 0.02f) ? 1 : 0);
			if (instance._hasMagState)
			{
				instance._magState.magazineData.rounds = MagCapacity;
			}
			if (!IsPumpShotgun)
			{
				instance.isSlideLockedOnEmpty = SlideLockedOnEmpty;
				instance.isSlideReleaseOnCollision = SlideReleaseOnCollision;
			}
			if (!HasInternalMagazine)
			{
				instance.isMagEjectOnEmpty = !MagEject;
			}
			foreach (Rigidbody componentsInChild in ((Component)((Component)instance).transform.root).GetComponentsInChildren<Rigidbody>())
			{
				string cleanObjectName = HelperMethods.GetCleanObjectName(((Object)componentsInChild).name);
				if (rbWeights.ContainsKey(cleanObjectName))
				{
					componentsInChild.mass = rbWeights[cleanObjectName] * (float)WeightMult;
				}
			}
		}
		if ((Object)(object)GunTweaker.controller != (Object)null && !GunTweaker.controller.isDevToolSpawned && HasBeenTweaked)
		{
			GunTweaker.controller.isDevToolSpawned = true;
		}
		Mag.rounds = MagCapacity;
	}
}
public class AmmoInfo
{
	public float Angle { get; set; }

	public int Count { get; set; }

	public float DamageMultiplier { get; set; }

	public float Mass { get; set; }

	public float StartVelocity { get; set; }

	public int DefaultMagCapacity { get; set; }

	public AmmoInfo(ProjectileData projectile, MagazineData mag)
	{
		Angle = projectile.angle;
		Count = projectile.count;
		DamageMultiplier = projectile.damageMultiplier;
		Mass = projectile.mass;
		StartVelocity = projectile.startVelocity;
		DefaultMagCapacity = mag.rounds;
	}
}
public class GunPref<T>
{
	public T[] profiles;

	private readonly bool multipleProfiles;

	private readonly GunInfo gunInfo;

	private T defaultValue;

	private T[] defaultArray;

	public int CurrProfile
	{
		get
		{
			if (!multipleProfiles)
			{
				return 0;
			}
			return gunInfo.CurrentProfile - 1;
		}
	}

	public GunPref(GunInfo gun, string name, T defaultVal, T[] value = null, bool multipleProfiles = true)
	{
		this.multipleProfiles = multipleProfiles;
		gunInfo = gun;
		T[] array = new T[(!this.multipleProfiles) ? 1 : 5];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = defaultVal;
		}
		profiles = value ?? array;
		defaultValue = defaultVal;
		defaultArray = array;
	}

	public void SetValue(T val)
	{
		Preferences.SavePrefs();
		profiles[CurrProfile] = val;
	}

	public T GetValue()
	{
		return profiles[CurrProfile];
	}

	public T GetDefaultValue()
	{
		return defaultValue;
	}

	public void Reset(bool allProfiles)
	{
		if (allProfiles)
		{
			profiles = defaultArray;
		}
		else
		{
			profiles[CurrProfile] = defaultValue;
		}
	}

	public static implicit operator T(GunPref<T> pref)
	{
		return pref.profiles[pref.CurrProfile];
	}
}
public static class BuildInfo
{
	public const string Name = "GunTweaker";

	public const string Author = "Adi";

	public const string Company = null;

	public const string Version = "1.1.4";

	public const string DownloadLink = null;
}
public class GunTweaker : MelonMod
{
	[HarmonyPatch(typeof(Gun), "Start")]
	public static class GunPatch
	{
		public static void Postfix(Gun __instance)
		{
			OnSpawn(__instance);
		}
	}

	[HarmonyPatch(typeof(Rigidbody), "AddForceAtPosition", new Type[]
	{
		typeof(Vector3),
		typeof(Vector3),
		typeof(ForceMode)
	})]
	public static class RecoilPatch
	{
		public static void Prefix(Rigidbody __instance, ref Vector3 force)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (isFiring && instanceToPool.TryGetValue(HelperMethods.GetCleanObjectName(((Object)((Component)__instance).transform.root).name), out var value) && gunInfo.TryGetValue(value, out var value2))
			{
				if ((bool)value2.ScaleRecoil)
				{
					force /= (float)value2.MassMult * (float)value2.VelocityMult;
				}
				force *= (float)value2.RecoilMult * Preferences.GlobalRecoilMultiplier.Value;
			}
		}
	}

	[HarmonyPatch(typeof(GunSFX), "MagazineInsert")]
	public static class MagPatchForModdedGunsBecauseTheyWorkDifferentlyForSomeFuckingReason_EVERYSINGLEVANILLAGUNJUSTUSESDEFAULTMAGAZINEWHYCANTMODDEDGUNSLIKEHOLYSHITDUDEWHYTHEFUCKDOIHAVETODOTHISSHITITMAKESZEROFUCKINGSENSEIALSOHAVETOPATCHGUNSFXMAGAZINEINSERTINSTEADOFGUNONMAGAZINEINSERTEDBECAUSEITDOESNTGETCALLEDCONSISTENTLYFORSOMEFUCKINGREASON_OKAPPARENTLYTHISISFORVANILLAGUNSASWELLNOWBECAUSETHEYBREAKINTHEARENAORSOMESHITIDONTEVENKNOWATTHISPOINTBRUH
	{
		public static void Postfix(GunSFX __instance)
		{
			if (SFXCache.TryGetValue(((Object)__instance).GetInstanceID(), out var value) && !((Object)(object)value == (Object)null) && value._hasMagState && TryGetGunInfo(value, out var info) && value._magState.magazineData.rounds != (int)info.MagCapacity)
			{
				value._magState.magazineData.rounds = info.MagCapacity;
				value._magState.SetCartridge((int)info.MagCapacity);
				value._magState.Refill();
			}
		}
	}

	[HarmonyPatch(typeof(Gun), "SlideLocked")]
	public static class SlideLockedPatch
	{
		public static void Prefix(Gun __instance)
		{
			if (TryGetGunInfo(__instance, out var info) && !info.HasInternalMagazine)
			{
				__instance.isMagEjectOnEmpty = info.AutoEject;
			}
		}

		public static void Postfix(Gun __instance)
		{
			if (TryGetGunInfo(__instance, out var info) && !info.HasInternalMagazine)
			{
				__instance.isMagEjectOnEmpty = !info.MagEject;
			}
		}
	}

	[HarmonyPatch(typeof(AmmoSocket), "UpdateProxyGripState")]
	public static class ProxyGripPatch
	{
		public static void Prefix(AmmoSocket __instance)
		{
			if (TryGetGunInfo(__instance.gun, out var info) && !info.HasInternalMagazine)
			{
				__instance.gun.isMagEjectOnEmpty = info.OGInfo.MagEjectOnEmpty;
			}
		}

		public static void Postfix(AmmoSocket __instance)
		{
			if (TryGetGunInfo(__instance.gun, out var info) && !info.HasInternalMagazine)
			{
				__instance.gun.isMagEjectOnEmpty = !info.MagEject;
			}
		}
	}

	public static Dictionary<string, string> instanceToPool = new Dictionary<string, string>();

	public static Dictionary<string, GunInfo> gunInfo = new Dictionary<string, GunInfo>();

	public static Page mainPage;

	public const string purpleHex = "#960ACD";

	public static BaseGameController controller;

	public static HashSet<string> internalGunNames = new HashSet<string>();

	public static bool fusionInstalled = false;

	public static List<Element> elements = null;

	public static Dictionary<int, Gun> SFXCache = new Dictionary<int, Gun>();

	public static bool isFiring = false;

	public static void AddToMenu(string gun)
	{
		if (elements == null)
		{
			elements = (List<Element>)typeof(Page).GetField("_elements", AccessTools.all).GetValue(mainPage);
		}
		int num = elements.FindIndex((Element i) => i.ElementName == gun);
		Element val = null;
		if (num != -1)
		{
			val = elements[num];
		}
		else if (elements.Count - 2 == 5)
		{
			elements.RemoveAt(elements.Count - 1);
		}
		if (val == null)
		{
			val = (Element)(object)CreateGunCategory(gun);
		}
		elements.Remove(val);
		elements.Insert(1, val);
	}

	public override void OnDeinitializeMelon()
	{
		Preferences.SavePrefs();
	}

	public static Color HexToColor(string hex)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		Color result = default(Color);
		ColorUtility.TryParseHtmlString("#960ACD", ref result);
		return result;
	}

	public override void OnInitializeMelon()
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		Preferences.LoadPrefs();
		mainPage = Page.Root.CreatePage((Random.RandomRangeInt(1, 100001) == 100000) ? "Gun Twerker" : "Gun Tweaker", HexToColor("#960ACD"), 0, true);
		((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(BaseGameController).GetMethod("OnEnable", AccessTools.all), (HarmonyMethod)null, MelonUtils.ToNewHarmonyMethod(typeof(GunTweaker).GetMethod("ControllerPatch", AccessTools.all)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		Page obj = mainPage.CreatePage("Global Modifiers", HexToColor("#960ACD"), 0, true);
		obj.CreateFloat("Firerate Multiplier", Color.yellow, Preferences.GlobalFirerateMultiplier.Value, 0.05f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			Preferences.GlobalFirerateMultiplier.Value = value;
			foreach (GunInfo value in gunInfo.Values)
			{
				value.ApplyTweaks();
			}
		});
		obj.CreateFloat("Damage Multiplier", Color.red, Preferences.GlobalDamageMultiplier.Value, 0.05f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			Preferences.GlobalDamageMultiplier.Value = value;
			foreach (GunInfo value2 in gunInfo.Values)
			{
				value2.ApplyTweaks();
			}
		});
		obj.CreateFloat("Projectile Mass Multiplier", Color.magenta, Preferences.GlobalMassMultiplier.Value, 0.05f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			Preferences.GlobalMassMultiplier.Value = value;
			foreach (GunInfo value3 in gunInfo.Values)
			{
				value3.ApplyTweaks();
			}
		});
		obj.CreateFloat("Projectile Velocity Multiplier", Color.cyan, Preferences.GlobalVelocityMultiplier.Value, 0.05f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			Preferences.GlobalVelocityMultiplier.Value = value;
			foreach (GunInfo value4 in gunInfo.Values)
			{
				value4.ApplyTweaks();
			}
		});
		obj.CreateFloat("Recoil Multiplier", Color.white, Preferences.GlobalRecoilMultiplier.Value, 0.05f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			Preferences.GlobalRecoilMultiplier.Value = value;
		});
		Hooking.OnMarrowGameStarted += delegate
		{
			//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_0035: Expected O, but got Unknown
			Enumerator<Barcode, Scannable> enumerator2 = AssetWarehouse.Instance.InventoryRegistry.Values.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				Scannable current2 = enumerator2.Current;
				SpawnableCrateReference val = new SpawnableCrateReference(current2.Barcode);
				SpawnableCrate val2 = (((int)val != 0) ? ((CrateReferenceT<SpawnableCrate>)val).Crate : null);
				if ((Object)(object)val2 != (Object)null && ((Crate)val2).Pallet.Internal && ((Crate)val2).Tags.Contains("Gun"))
				{
					internalGunNames.Add(current2.Title.Trim());
				}
			}
		};
		Hooking.OnGrabObject += OnGrabObject;
		Hooking.OnLevelUnloaded += delegate
		{
			foreach (GunInfo value5 in gunInfo.Values)
			{
				value5.Instances.Clear();
				value5.InstanceIds.Clear();
				SFXCache.Clear();
			}
		};
	}

	public override void OnLateInitializeMelon()
	{
		fusionInstalled = MelonTypeBase<MelonMod>.RegisteredMelons.Any((MelonMod i) => ((MelonBase)i).Info.Name == "LabFusion");
	}

	public static void OnGrabObject(GameObject go, Hand hand)
	{
		string gunName = GetGunName(((Object)go.transform.root).name);
		if (gunName != null)
		{
			AddToMenu(gunName);
		}
	}

	public static PageLinkElement CreateGunCategory(string name)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: 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_0094: 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_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0426: 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_0482: Unknown result type (might be due to invalid IL or missing references)
		//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0557: Unknown result type (might be due to invalid IL or missing references)
		//IL_0598: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0647: Unknown result type (might be due to invalid IL or missing references)
		//IL_0664: Unknown result type (might be due to invalid IL or missing references)
		//IL_0675: Unknown result type (might be due to invalid IL or missing references)
		//IL_067b: Expected O, but got Unknown
		//IL_0528: Unknown result type (might be due to invalid IL or missing references)
		if (!gunInfo.TryGetValue(name, out var info))
		{
			return null;
		}
		Page gunCat = mainPage.CreatePage(name, Color.white, 0, false);
		IntElement profile = gunCat.CreateInt("Profile", Color.white, info.CurrentProfile, 1, 0, 6, (Action<int>)null);
		Page val = gunCat.CreatePage("Modifiers", Color.yellow, 0, true);
		Page val2 = gunCat.CreatePage("Miscellaneous Options", Color.green, 0, true);
		FloatElement fr = val.CreateFloat("Firerate Multiplier", Color.yellow, (float)info.FireRateMult, 0.05f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			info.FireRateMult.SetValue(value);
			info.ApplyTweaks();
		});
		FloatElement dmg = val.CreateFloat("Damage Multiplier", Color.red, (float)info.DamageMult, 0.05f, float.MinValue, float.MaxValue, (Action<float>)delegate(float value)
		{
			info.DamageMult.SetValue(value);
			info.ApplyTweaks();
		});
		FloatElement mass = val.CreateFloat("Projectile Mass Multiplier", Color.magenta, (float)info.MassMult, 0.1f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			info.MassMult.SetValue(value);
			info.ApplyTweaks();
		});
		FloatElement proj = val.CreateFloat("Projectile Velocity Multiplier", Color.cyan, (float)info.VelocityMult, 0.1f, 0f, float.MaxValue, (Action<float>)delegate(float value)
		{
			info.VelocityMult.SetValue(value);
			info.ApplyTweaks();
		});
		IntElement burst = null;
		IntElement mag = null;
		Action action = null;
		EnumElement fMode = null;
		List<Element> _elements = (List<Element>)typeof(Page).GetField("_elements", AccessTools.all).GetValue(gunCat);
		fMode = gunCat.CreateEnum("Firemode", Color.green, (Enum)info.FireMode.GetValue(), (Action<Enum>)delegate(Enum e)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			FiremodeGarbage.Firemode firemode = (FiremodeGarbage.Firemode)(object)e;
			info.FireMode.SetValue(firemode);
			info.ApplyTweaks();
			if (firemode == FiremodeGarbage.Firemode.Burst)
			{
				burst = gunCat.CreateInt("Rounds Per Burst", HexToColor("#CC5500"), (int)info.BurstSize, 1, 2, int.MaxValue, (Action<int>)delegate(int value)
				{
					info.BurstSize.SetValue(value);
				});
				_elements.Remove((Element)(object)burst);
				_elements.Insert(4, (Element)(object)burst);
			}
			else
			{
				_elements.Remove((Element)(object)burst);
			}
			Menu.OpenPage(gunCat);
		});
		burst = gunCat.CreateInt("Rounds Per Burst", HexToColor("#CC5500"), (int)info.BurstSize, 1, 2, int.MaxValue, (Action<int>)delegate(int value)
		{
			info.BurstSize.SetValue(value);
		});
		if ((FiremodeGarbage.Firemode)info.FireMode != FiremodeGarbage.Firemode.Burst)
		{
			gunCat.Remove((Element)(object)burst);
		}
		mag = gunCat.CreateInt("Magazine Capacity", Color.white, (int)info.MagCapacity, 1, 1, int.MaxValue, (Action<int>)delegate(int value)
		{
			info.MagCapacity.SetValue(value);
			info.ApplyTweaks();
		});
		BoolElement inf = val2.CreateBool("Infinite Ammo", Color.magenta, (bool)info.InfiniteAmmo, (Action<bool>)delegate(bool value)
		{
			info.InfiniteAmmo.SetValue(value);
		});
		BoolElement slide = null;
		BoolElement sLock = null;
		if (!info.IsPumpShotgun)
		{
			slide = val2.CreateBool("Slide Release On Collision", Color.cyan, (bool)info.SlideReleaseOnCollision, (Action<bool>)delegate(bool value)
			{
				info.SlideReleaseOnCollision.SetValue(value);
				info.ApplyTweaks();
			});
			sLock = val2.CreateBool("Slide Locked On Empty", Color.green, (bool)info.SlideLockedOnEmpty, (Action<bool>)delegate(bool value)
			{
				info.SlideLockedOnEmpty.SetValue(value);
				info.ApplyTweaks();
			});
		}
		BoolElement magEject = null;
		BoolElement autoEject = null;
		if (!info.HasInternalMagazine)
		{
			magEject = val2.CreateBool("Mag Eject", Color.white, (bool)info.MagEject, (Action<bool>)delegate(bool value)
			{
				info.MagEject.SetValue(value);
				info.ApplyTweaks();
			});
			autoEject = val2.CreateBool("Auto Eject Mag", HexToColor("#CC5500"), (bool)info.AutoEject, (Action<bool>)delegate(bool value)
			{
				info.AutoEject.SetValue(value);
			});
		}
		Page val3 = null;
		BoolElement enabled = null;
		Action<int> action2 = delegate(int value)
		{
			info.ProjCount.SetValue(value);
			info.ApplyTweaks();
		};
		Action<float> action3 = delegate(float value)
		{
			info.Spread.SetValue(value);
			info.ApplyTweaks();
		};
		if (!info.IsShotgun)
		{
			val3 = val2.CreatePage("Pseudo Shotgun", Color.red, 0, true);
		}
		enabled = ((val3 != null) ? val3.CreateBool("Enabled", Color.white, (bool)info.PseudoShotgun, (Action<bool>)delegate(bool value)
		{
			info.PseudoShotgun.SetValue(value);
			info.ApplyTweaks();
		}) : null);
		FloatElement spread = ((val3 != null) ? val3.CreateFloat("Spread", HexToColor("#CC5500"), (float)info.Spread, 0.1f, 0f, float.MaxValue, action3) : null) ?? val.CreateFloat("Spread", HexToColor("#CC5500"), (float)info.Spread, 0.1f, 0f, float.MaxValue, action3);
		IntElement projCount = ((val3 != null) ? val3.CreateInt("Pellets", Color.magenta, (int)info.ProjCount, 1, 0, int.MaxValue, action2) : null) ?? val.CreateInt("Pellets", Color.white, (int)info.ProjCount, 1, 0, int.MaxValue, action2);
		FloatElement recoil = val.CreateFloat("Recoil Multiplier", Color.white, (float)info.RecoilMult, 0.05f, float.MinValue, float.MaxValue, (Action<float>)delegate(float value)
		{
			info.RecoilMult.SetValue(value);
		});
		FloatElement weight = val.CreateFloat("Weight Multiplier", Color.green, (float)info.WeightMult, 0.05f, float.MinValue, float.MaxValue, (Action<float>)delegate(float value)
		{
			info.WeightMult.SetValue(value);
			info.ApplyTweaks();
		});
		val.CreateBool("Scale Recoil With Mass & Velocity", Color.red, (bool)info.ScaleRecoil, (Action<bool>)delegate(bool value)
		{
			info.ScaleRecoil.SetValue(value);
		});
		typeof(IntElement).GetField("_callback", AccessTools.all).SetValue(profile, (Action<int>)delegate(int value)
		{
			value = value switch
			{
				0 => 5, 
				6 => 1, 
				_ => value, 
			};
			info.CurrentProfile = value;
			profile.Value = value;
			SetValues();
		});
		action = delegate
		{
			info.Reset();
			SetValues();
		};
		gunCat.CreateFunction("Reset Profile", Color.red, action);
		return new PageLinkElement(gunCat.Name, gunCat.Color, (Action)delegate
		{
			Menu.OpenPage(gunCat);
		});
		void SetValues()
		{
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			fr.Value = info.FireRateMult;
			dmg.Value = info.DamageMult;
			mass.Value = info.MassMult;
			proj.Value = info.VelocityMult;
			fMode.Value = (FiremodeGarbage.Firemode)info.FireMode;
			burst.Value = info.BurstSize;
			mag.Value = info.MagCapacity;
			if (slide != null)
			{
				slide.Value = info.SlideReleaseOnCollision;
			}
			inf.Value = info.InfiniteAmmo;
			if (sLock != null)
			{
				sLock.Value = info.SlideLockedOnEmpty;
			}
			if (magEject != null)
			{
				magEject.Value = info.MagEject;
			}
			if (magEject != null)
			{
				autoEject.Value = info.AutoEject;
			}
			projCount.Value = info.ProjCount;
			spread.Value = info.Spread;
			if (enabled != null)
			{
				enabled.Value = info.PseudoShotgun;
			}
			recoil.Value = info.RecoilMult;
			weight.Value = info.WeightMult;
			gunCat.Remove((Element)(object)burst);
			if ((FiremodeGarbage.Firemode)(object)fMode.Value == FiremodeGarbage.Firemode.Burst)
			{
				burst = gunCat.CreateInt("Rounds Per Burst", HexToColor("#CC5500"), (int)info.BurstSize, 1, 2, int.MaxValue, (Action<int>)delegate(int value)
				{
					info.BurstSize.SetValue(value);
				});
				_elements.Remove((Element)(object)burst);
				_elements.Insert(4, (Element)(object)burst);
			}
			Menu.OpenPage(gunCat);
			info.ApplyTweaks();
		}
	}

	public static void ControllerPatch(BaseGameController __instance)
	{
		controller = __instance;
	}

	public static bool TryGetGunInfo(Gun gun, out GunInfo info)
	{
		info = null;
		string gunName = GetGunName(gun);
		if (string.IsNullOrEmpty(gunName))
		{
			return false;
		}
		return gunInfo.TryGetValue(gunName, out info);
	}

	public static bool TryGetGunInfo(string name, out GunInfo info)
	{
		info = null;
		name = GetGunName(name);
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		return gunInfo.TryGetValue(name, out info);
	}

	public static string GetGunName(Gun gun)
	{
		string gunName = GetGunName(HelperMethods.GetCleanObjectName(((Object)((Component)gun).transform.root).name));
		if (gunName != null)
		{
			return gunName;
		}
		object obj;
		if (gun == null)
		{
			obj = null;
		}
		else
		{
			Poolee poolee = ((SpawnEvents)gun)._poolee;
			obj = ((poolee != null) ? poolee.SpawnableCrate : null);
		}
		SpawnableCrate val = (SpawnableCrate)obj;
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		return (!((Crate)val).Pallet.Internal && internalGunNames.Contains(((Scannable)val).Title)) ? (((Crate)val).Pallet.Author + " - " + ((Scannable)val).Title) : ((Scannable)val).Title;
	}

	public static string GetGunName(string gun)
	{
		string cleanObjectName = HelperMethods.GetCleanObjectName(gun);
		if (instanceToPool.TryGetValue(cleanObjectName, out var value))
		{
			return value;
		}
		return null;
	}

	public static void OnSpawn(Gun gun)
	{
		string cleanObjectName = HelperMethods.GetCleanObjectName(((Object)((Component)gun).transform.root).name);
		if (cleanObjectName == "SPAWN_GUN")
		{
			return;
		}
		try
		{
			string gunName = GetGunName(gun);
			if (!instanceToPool.ContainsKey(cleanObjectName) && gunName != null)
			{
				instanceToPool.Add(cleanObjectName, gunName);
			}
			if (gunName != null && !gunInfo.ContainsKey(gunName))
			{
				gunInfo.Add(gunName, new GunInfo(gun, gunName));
			}
			int instanceID = ((Object)gun).GetInstanceID();
			if (gunInfo.TryGetValue(instanceToPool[cleanObjectName], out var value) && value.InstanceIds.Add(instanceID) && value.Instances.Add(gun))
			{
				SFXCache.Add(((Object)gun.gunSFX).GetInstanceID(), gun);
				value.ApplyTweaks(gun);
			}
		}
		catch (Exception ex)
		{
			object obj;
			if (gun == null)
			{
				obj = null;
			}
			else
			{
				Poolee poolee = ((SpawnEvents)gun)._poolee;
				obj = ((poolee != null) ? poolee.SpawnableCrate : null);
			}
			SpawnableCrate val = (SpawnableCrate)obj;
			string text = (((Object)(object)val != (Object)null) ? (((Crate)val).Pallet.Author + " - " + ((Scannable)val).Title) : cleanObjectName);
			MelonLogger.Msg(ConsoleColor.Red, text);
			MelonLogger.Error((object)ex);
		}
	}
}
public static class Preferences
{
	public class GunPref
	{
		public string Name;

		public int CurrentProfile;

		public float[] FirerateMultiplier;

		public float[] DamageMultiplier;

		public float[] ProjectileMassMultiplier;

		public float[] ProjectileVelocityMultiplier;

		public int[] RoundsPerBurst;

		public FiremodeGarbage.Firemode[] Firemode;

		public int[] MagazineCapacity;

		public bool[] InfiniteAmmo;

		public bool[] SlideLock;

		public bool[] SlideReleaseOnCollision;

		public bool[] MagEject;

		public bool[] AutoEject;

		public bool[] PseudoShotgun;

		public int[] ProjectileCount;

		public float[] Spread;

		public float[] RecoilMult;

		public float[] WeightMult;

		public bool[] ScaleRecoil;

		public GunPref()
		{
		}

		public GunPref(GunInfo info)
		{
			Name = info.Name;
			CurrentProfile = info.CurrentProfile;
			FirerateMultiplier = info.FireRateMult?.profiles;
			DamageMultiplier = info.DamageMult?.profiles;
			ProjectileMassMultiplier = info.MassMult?.profiles;
			ProjectileVelocityMultiplier = info.VelocityMult?.profiles;
			MagazineCapacity = info.MagCapacity?.profiles;
			Firemode = info.FireMode?.profiles;
			RoundsPerBurst = info.BurstSize?.profiles;
			SlideReleaseOnCollision = info.SlideReleaseOnCollision?.profiles;
			InfiniteAmmo = info.InfiniteAmmo?.profiles;
			PseudoShotgun = info.PseudoShotgun?.profiles;
			ProjectileCount = info.ProjCount?.profiles;
			Spread = info.Spread?.profiles;
			SlideLock = info.SlideLockedOnEmpty?.profiles;
			MagEject = info.MagEject?.profiles;
			AutoEject = info.AutoEject?.profiles;
			RecoilMult = info.RecoilMult?.profiles;
			WeightMult = info.WeightMult?.profiles;
			ScaleRecoil = info.ScaleRecoil?.profiles;
		}
	}

	public static string path = Path.Combine(MelonEnvironment.UserDataDirectory, "GunTweakerPrefs.cfg");

	public static MelonPreferences_Category cat = MelonPreferences.CreateCategory("GlobalModifiers");

	public static MelonPreferences_Entry<float> GlobalFirerateMultiplier = cat.CreateEntry<float>("FirerateMultiplier", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);

	public static MelonPreferences_Entry<float> GlobalDamageMultiplier = cat.CreateEntry<float>("DamageMultiplier", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);

	public static MelonPreferences_Entry<float> GlobalMassMultiplier = cat.CreateEntry<float>("ProjectileMassMultiplier", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);

	public static MelonPreferences_Entry<float> GlobalVelocityMultiplier = cat.CreateEntry<float>("ProjectileVelocityMultiplier", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);

	public static MelonPreferences_Entry<float> GlobalRecoilMultiplier = cat.CreateEntry<float>("RecoilMultiplier", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);

	public static MelonPreferences_Entry<List<GunPref>> GunPrefs = cat.CreateEntry<List<GunPref>>("GunPrefs", new List<GunPref>(), (string)null, (string)null, false, false, (ValueValidator)null, (string)null);

	public static void LoadPrefs()
	{
		FixPrefs();
		cat.SetFilePath(path, true, false);
		cat.SaveToFile(false);
		foreach (GunPref item in GunPrefs.Value)
		{
			GunInfo.gunPrefs.Add(item.Name, item);
		}
	}

	public static void FixPrefs()
	{
		if (!File.Exists(path) || GunPrefs.Value.Count > 0)
		{
			return;
		}
		TomlDocument val = TomlParser.ParseFile(path);
		Type[] array = new Type[6]
		{
			typeof(int),
			typeof(bool[]),
			typeof(int[]),
			typeof(float[]),
			typeof(float),
			typeof(FiremodeGarbage.Firemode[])
		};
		foreach (KeyValuePair<string, TomlValue> entry in ((TomlTable)val).Entries)
		{
			if (entry.Key.Contains("GlobalModifiers"))
			{
				continue;
			}
			TomlTable subTable = ((TomlTable)val).GetSubTable(entry.Key);
			GunPref gunPref = new GunPref
			{
				Name = entry.Key.Replace(" Config", "")
			};
			foreach (KeyValuePair<string, TomlValue> entry2 in subTable.Entries)
			{
				object obj = null;
				Type[] array2 = array;
				foreach (Type type in array2)
				{
					try
					{
						obj = TomletMain.To(type, entry2.Value, (TomlSerializerOptions)null);
					}
					catch (Exception)
					{
						continue;
					}
					break;
				}
				if (obj != null)
				{
					typeof(GunPref).GetField(entry2.Key)?.SetValue(gunPref, obj);
				}
			}
			GunPrefs.Value.Add(gunPref);
		}
	}

	public static void SavePrefs()
	{
		new List<GunPref>();
		foreach (GunInfo value in GunTweaker.gunInfo.Values)
		{
			if (GunInfo.gunPrefs.ContainsKey(value.Name))
			{
				GunInfo.gunPrefs[value.Name] = new GunPref(value);
			}
			else
			{
				GunInfo.gunPrefs.Add(value.Name, new GunPref(value));
			}
		}
		GunPrefs.Value = GunInfo.gunPrefs.Values.ToList();
	}
}