Decompiled source of HandgunEnhancementMod v1.3.0

Handgun Mod.dll

Decompiled 10 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Handgun Mod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Handgun Mod")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5dca9d7d-cc77-4ee6-9aec-237cd43472c9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.Dileppy.repomods.HandgunEnhancementMod", "Handgun Enhancement Mod", "1.3.0")]
public class HandgunRateMod : BaseUnityPlugin
{
	[HarmonyPatch]
	private static class Patch_StateReloading
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("ItemGun");
			if (type == null)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					type = assembly.GetType("ItemGun");
					if (type != null)
					{
						break;
					}
				}
			}
			if (type == null)
			{
				Debug.LogError((object)"[HandgunRateMod] Could not find ItemGun type.");
				return null;
			}
			return AccessTools.Method(type, "StateReloading", new Type[1] { typeof(bool) }, (Type[])null);
		}

		private static void Postfix(object __instance)
		{
			try
			{
				if (!IsRuntimeEnabled() || __instance == null)
				{
					return;
				}
				Type type = __instance.GetType();
				FieldInfo field = type.GetField("shootCooldown", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = type.GetField("stateTimeMax", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null) && !(field2 == null))
				{
					float num = Convert.ToSingle(field.GetValue(__instance));
					float num2 = Math.Max(0f, CooldownMultiplier.Value);
					float num3 = num * num2;
					bool value = AllowFullAuto.Value;
					float value2 = MinAllowedCooldown.Value;
					float num4 = num3;
					if (!value && num4 < value2)
					{
						num4 = value2;
					}
					field2.SetValue(__instance, num4);
					if (Time.frameCount % 300 == 0)
					{
						Debug.Log((object)$"[HandgunRateMod] Applied cooldown multiplier {num2} (shootCooldown={num}) => stateTimeMax={num4} (allowFull={value})");
					}
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[HandgunRateMod] StateReloading.Postfix error: {arg}");
			}
		}
	}

	[HarmonyPatch]
	private static class Patch_ItemGun_Start
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("ItemGun");
			if (type == null)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					type = assembly.GetType("ItemGun");
					if (type != null)
					{
						break;
					}
				}
			}
			if (type == null)
			{
				return null;
			}
			return AccessTools.Method(type, "Start", Type.EmptyTypes, (Type[])null);
		}

		private static void Postfix(object __instance)
		{
			try
			{
				if (IsRuntimeEnabled() && __instance != null)
				{
					Type type = __instance.GetType();
					FieldInfo field = type.GetField("batteryDrain", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						float num = Convert.ToSingle(field.GetValue(__instance));
						float num2 = num * BatteryDrainMultiplier.Value;
						field.SetValue(__instance, num2);
					}
					FieldInfo field2 = type.GetField("numberOfBullets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 != null)
					{
						field2.SetValue(__instance, BulletCountOverride.Value);
					}
					FieldInfo field3 = type.GetField("gunRecoilForce", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo field4 = type.GetField("cameraShakeMultiplier", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo field5 = type.GetField("torqueMultiplier", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (ZeroRecoil.Value)
					{
						field3?.SetValue(__instance, 0f);
						field4?.SetValue(__instance, 0f);
						field5?.SetValue(__instance, 0f);
					}
					FieldInfo field6 = type.GetField("gunRandomSpread", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (PerfectAccuracy.Value && field6 != null)
					{
						field6.SetValue(__instance, 0f);
					}
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[HandgunRateMod] ItemGun.Start postfix error: {arg}");
			}
		}
	}

	[HarmonyPatch]
	private static class Patch_ItemGunBullet_ActivateAll
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("ItemGunBullet");
			if (type == null)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					type = assembly.GetType("ItemGunBullet");
					if (type != null)
					{
						break;
					}
				}
			}
			if (type == null)
			{
				Debug.LogWarning((object)"[HandgunRateMod] ItemGunBullet type not found; bullet modifications disabled.");
				return null;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "ActivateAll", Type.EmptyTypes, (Type[])null);
			if (methodInfo == null)
			{
				Debug.LogWarning((object)"[HandgunRateMod] ItemGunBullet.ActivateAll not found; bullet modifications disabled.");
			}
			return methodInfo;
		}

		private static void Postfix(object __instance)
		{
			try
			{
				if (!IsRuntimeEnabled() || __instance == null)
				{
					return;
				}
				Type type = __instance.GetType();
				string[] array = new string[5] { "speed", "bulletSpeed", "velocity", "bulletVelocity", "moveSpeed" };
				string[] array2 = array;
				foreach (string name in array2)
				{
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null && (field.FieldType == typeof(float) || field.FieldType == typeof(double)))
					{
						float num = Convert.ToSingle(field.GetValue(__instance));
						float value = num * BulletSpeedMultiplier.Value;
						field.SetValue(__instance, ConvertFieldValue(field.FieldType, value));
						break;
					}
				}
				string[] array3 = new string[4] { "damage", "hitDamage", "damageAmount", "hurtAmount" };
				string[] array4 = array3;
				foreach (string name2 in array4)
				{
					FieldInfo field2 = type.GetField(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 != null && (field2.FieldType == typeof(float) || field2.FieldType == typeof(double) || field2.FieldType == typeof(int)))
					{
						float num2 = Convert.ToSingle(field2.GetValue(__instance));
						float value2 = num2 * BulletDamageMultiplier.Value;
						field2.SetValue(__instance, ConvertFieldValue(field2.FieldType, value2));
						break;
					}
				}
				if (ExplosiveBullets.Value)
				{
					string[] array5 = new string[3] { "explosive", "isExplosive", "explodeOnHit" };
					string[] array6 = array5;
					foreach (string name3 in array6)
					{
						FieldInfo field3 = type.GetField(name3, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field3 != null && field3.FieldType == typeof(bool))
						{
							field3.SetValue(__instance, true);
							break;
						}
					}
				}
				if (!PenetrationEnabled.Value)
				{
					return;
				}
				string[] array7 = new string[5] { "penetrationCount", "penetration", "maxPenetrations", "pierceCount", "pierce" };
				string[] array8 = array7;
				foreach (string name4 in array8)
				{
					FieldInfo field4 = type.GetField(name4, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field4 != null)
					{
						if (field4.FieldType == typeof(int))
						{
							field4.SetValue(__instance, PenetrationCount.Value);
						}
						else
						{
							field4.SetValue(__instance, ConvertFieldValue(field4.FieldType, PenetrationCount.Value));
						}
						break;
					}
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[HandgunRateMod] ItemGunBullet.ActivateAll postfix error: {arg}");
			}
		}

		private static object ConvertFieldValue(Type fieldType, float value)
		{
			if (fieldType == typeof(float))
			{
				return value;
			}
			if (fieldType == typeof(double))
			{
				return (double)value;
			}
			if (fieldType == typeof(int))
			{
				return (int)Math.Round(value);
			}
			return value;
		}
	}

	public static ConfigEntry<float> CooldownMultiplier;

	public static ConfigEntry<float> BatteryDrainMultiplier;

	public static ConfigEntry<int> BulletCountOverride;

	public static ConfigEntry<bool> ZeroRecoil;

	public static ConfigEntry<bool> PerfectAccuracy;

	public static ConfigEntry<float> BulletSpeedMultiplier;

	public static ConfigEntry<float> BulletDamageMultiplier;

	public static ConfigEntry<bool> ExplosiveBullets;

	public static ConfigEntry<float> ExplosionRadius;

	public static ConfigEntry<bool> PenetrationEnabled;

	public static ConfigEntry<int> PenetrationCount;

	public static ConfigEntry<KeyCode> ToggleKey;

	public static ConfigEntry<bool> AllowFullAuto;

	public static ConfigEntry<float> MinAllowedCooldown;

	private Harmony _harmony;

	private bool _enabled = true;

	private void Awake()
	{
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Expected O, but got Unknown
		CooldownMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CooldownMultiplier", 0.25f, "Multiply shootCooldown (1=normal, 0.25=4x faster, 0=instant/full-auto if AllowFullAuto=true)");
		BatteryDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BatteryDrainMultiplier", 0.1f, "Multiply battery drain (0=infinite)");
		BulletCountOverride = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BulletMultiplier", 2, "Override numberOfBullets");
		ZeroRecoil = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ZeroRecoil", true, "Removes recoil force and camera shake");
		PerfectAccuracy = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PerfectAccuracy", false, "Removes spread / randomness and may also crash game");
		BulletSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Bullet", "BulletSpeedMultiplier", 1.5f, "Multiply instantiated bullet speed (1=unchanged)");
		BulletDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Bullet", "BulletDamageMultiplier", 1.5f, "Multiply bullet damage (1=unchanged)");
		ExplosiveBullets = ((BaseUnityPlugin)this).Config.Bind<bool>("Bullet", "ExplosiveBullets", false, "If true, try to mark bullets explosive / create explosion on hit");
		ExplosionRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Bullet", "ExplosionRadius", 2.5f, "Explosion radius if explosives are supported");
		PenetrationEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Bullet", "EnablePenetration", false, "Allow bullets to penetrate targets if supported");
		PenetrationCount = ((BaseUnityPlugin)this).Config.Bind<int>("Bullet", "PenetrationCount", 2, "How many objects a penetrating bullet can pass through");
		ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)288, "Toggle the mod ON/OFF with this key");
		AllowFullAuto = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "AllowFullAuto", false, "Allow zero cooldown (danger: may cause infinite bullet loops). Default false.");
		MinAllowedCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "MinAllowedCooldown", 0.02f, "Minimum allowed effective cooldown (seconds) unless AllowFullAuto=true.");
		_harmony = new Harmony("com.Dileppy.repomods.HandgunEnhancementMod");
		try
		{
			_harmony.PatchAll();
			Debug.Log((object)$"[HandgunRateMod] Patched. CooldownMultiplier={CooldownMultiplier.Value}, BulletSpeed x{BulletSpeedMultiplier.Value}");
		}
		catch (Exception arg)
		{
			Debug.LogError((object)$"[HandgunRateMod] PatchAll failed: {arg}");
		}
	}

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

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		if (Input.GetKeyDown(ToggleKey.Value))
		{
			_enabled = !_enabled;
			Debug.Log((object)$"[HandgunRateMod] Toggled enabled => {_enabled}");
		}
	}

	private static bool IsRuntimeEnabled()
	{
		try
		{
			HandgunRateMod handgunRateMod = Object.FindObjectOfType<HandgunRateMod>();
			if ((Object)(object)handgunRateMod == (Object)null)
			{
				return true;
			}
			FieldInfo field = typeof(HandgunRateMod).GetField("_enabled", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				return Convert.ToBoolean(field.GetValue(handgunRateMod));
			}
			return true;
		}
		catch
		{
			return true;
		}
	}
}