Decompiled source of SolidAim v0.1.5

SolidAim.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
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("SolidAim")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jangnana")]
[assembly: AssemblyProduct("SolidAim")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e586ebd9-69f1-4ec0-8bab-8f11d86d3340")]
[assembly: AssemblyFileVersion("0.1.5.5")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.1.5.5")]
namespace SolidAim;

[BepInPlugin("Jangnana.SolidAim", "SolidAim", "0.1.5")]
public class SolidAim : BaseUnityPlugin
{
	public static SolidAim Instance;

	private readonly Harmony harmony = new Harmony("Jangnana.SolidAim");

	public static ConfigEntry<bool> AimStabilizationEnabled;

	public static ConfigEntry<bool> DebugMode;

	public static ConfigEntry<float> GunSpread;

	public static ConfigEntry<bool> DroopWhenEmpty;

	public static ConfigEntry<bool> AntiStuck;

	public static ConfigEntry<KeyCode> StuckRecoverKey;

	private float lastRecoveryTime = -3f;

	private void Awake()
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		Instance = this;
		AimStabilizationEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("AimSettings", "AimStabilization", true, "Enables fixed gun aiming and camera alignment logic.");
		DroopWhenEmpty = ((BaseUnityPlugin)this).Config.Bind<bool>("AimSettings", "DroopWhenEmpty", true, "Allows the gun to droop when out of ammo (Vanilla behavior).");
		GunSpread = ((BaseUnityPlugin)this).Config.Bind<float>("GunSettings", "GunSpread", 0f, new ConfigDescription("Bullet spread multiplier (0.0: No spread, 1.0: Vanilla).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		AntiStuck = ((BaseUnityPlugin)this).Config.Bind<bool>("GunSettings", "AntiStuck", true, "Automatically detects and recovers guns stuck in terrain.");
		StuckRecoverKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "StuckRecoverKey", (KeyCode)98, "Hotkey to manually recover your held weapon (3s cooldown).");
		DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugMode", false, "Show development logs in the console.");
		harmony.PatchAll(Assembly.GetExecutingAssembly());
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[SolidAim] v0.1.5 initialized successfully!");
	}

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		if (!Input.GetKeyDown(StuckRecoverKey.Value))
		{
			return;
		}
		if (Time.time - lastRecoveryTime < 3f)
		{
			if (DebugMode.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Recovery cooldown: {1:F1}s remaining.", "SolidAim", 3f - (Time.time - lastRecoveryTime)));
			}
		}
		else if (SolidAimHandler.RecoverStuckWeapons())
		{
			lastRecoveryTime = Time.time;
			if (DebugMode.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[SolidAim] Manual Recovery Success. Cooldown started (3s).");
			}
		}
		else if (DebugMode.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[SolidAim] No weapon held. Cooldown skipped.");
		}
	}
}
public static class PluginInfo
{
	public const string PLUGIN_GUID = "Jangnana.SolidAim";

	public const string PLUGIN_NAME = "SolidAim";

	public const string PLUGIN_VERSION = "0.1.5";

	public const string ASSEMBLY_VERSION = "0.1.5.5";
}
[HarmonyPatch(typeof(PhysGrabObject))]
public class SolidAimHandler : MonoBehaviour
{
	private static Dictionary<int, float> originalSpreads = new Dictionary<int, float>();

	private static Dictionary<int, float> lastAppliedMultipliers = new Dictionary<int, float>();

	private static Dictionary<int, float> lastBatteryLevels = new Dictionary<int, float>();

	private static Dictionary<int, Vector3> lastPos = new Dictionary<int, Vector3>();

	private static Dictionary<int, float> thrashTimer = new Dictionary<int, float>();

	private static HashSet<int> recoveryQueue = new HashSet<int>();

	private static float lastBatteryUpdateTime = 0f;

	private static bool isResourceEmpty = false;

	private static FieldInfo isCrouchingField = typeof(PlayerAvatar).GetField("isCrouching", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static FieldInfo gunStateField = typeof(ItemGun).GetField("stateCurrent", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo gunBatteryField = typeof(ItemGun).GetField("itemBattery", BindingFlags.Instance | BindingFlags.NonPublic);

	private static int layerMask = LayerMask.GetMask(new string[4] { "Default", "Environment", "Terrain", "Static" });

	public static void RestoreWeaponPhysics(PhysGrabObject obj, int gunId)
	{
		obj.rb.isKinematic = false;
		obj.rb.detectCollisions = true;
		recoveryQueue.Remove(gunId);
		if (SolidAim.DebugMode.Value)
		{
			Debug.Log((object)string.Format("[{0}] Manual Recovery Applied for {1}({2})", "SolidAim", ((Object)obj).name, gunId));
		}
	}

	public static bool RecoverStuckWeapons()
	{
		PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		bool result = false;
		PhysGrabObject[] array = Object.FindObjectsOfType<PhysGrabObject>();
		PhysGrabObject[] array2 = array;
		foreach (PhysGrabObject val2 in array2)
		{
			ItemGun component = ((Component)val2).GetComponent<ItemGun>();
			if (!((Object)(object)component == (Object)null))
			{
				if (recoveryQueue.Contains(((Object)component).GetInstanceID()))
				{
					RestoreWeaponPhysics(val2, ((Object)component).GetInstanceID());
				}
				if (val2.playerGrabbing != null && val2.playerGrabbing.Contains(val.physGrabber))
				{
					ExecuteRecovery(val2, val);
					result = true;
				}
			}
		}
		return result;
	}

	private static void ExecuteRecovery(PhysGrabObject obj, PlayerAvatar player)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_006c: Unknown result type (might be due to invalid IL or missing references)
		//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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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)
		Rigidbody rb = obj.rb;
		if (!((Object)(object)rb == (Object)null))
		{
			Transform val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform : ((Component)player).transform);
			rb.position = val.position + val.forward * 0.5f + val.right * 0.01f + val.up * 0.01f;
			rb.velocity = Vector3.zero;
			rb.angularVelocity = Vector3.zero;
			rb.rotation = val.rotation;
			rb.isKinematic = true;
			rb.detectCollisions = false;
			ItemGun component = ((Component)obj).GetComponent<ItemGun>();
			int instanceID = ((Object)component).GetInstanceID();
			recoveryQueue.Add(instanceID);
			if (SolidAim.DebugMode.Value)
			{
				Debug.Log((object)string.Format("[{0}] Recovery Enqueued for {1}({2})", "SolidAim", ((Object)component).name, instanceID));
			}
		}
	}

	[HarmonyPatch("FixedUpdate")]
	[HarmonyPostfix]
	private static void FixedUpdatePostfix(PhysGrabObject __instance)
	{
		ItemGun component = ((Component)__instance).GetComponent<ItemGun>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)component).GetInstanceID();
		if (recoveryQueue.Contains(instanceID))
		{
			RestoreWeaponPhysics(__instance, instanceID);
		}
		PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
		if ((Object)(object)val == (Object)null || !__instance.playerGrabbing.Contains(val.physGrabber))
		{
			return;
		}
		float value = SolidAim.GunSpread.Value;
		if (!originalSpreads.ContainsKey(instanceID))
		{
			originalSpreads[instanceID] = component.gunRandomSpread;
			lastAppliedMultipliers[instanceID] = -1f;
			if (SolidAim.DebugMode.Value)
			{
				Debug.Log((object)string.Format("[{0}] Detected: {1}({2}) (Original Spread: {3})", "SolidAim", ((Object)component).name, instanceID, originalSpreads[instanceID]));
			}
		}
		if (value != lastAppliedMultipliers[instanceID])
		{
			float num = originalSpreads[instanceID] * value;
			if (SolidAim.DebugMode.Value)
			{
				if (lastAppliedMultipliers[instanceID] == -1f)
				{
					Debug.Log((object)string.Format("[{0}] {1}({2}) Initial Spread Applied: {3} -> {4}", "SolidAim", ((Object)component).name, instanceID, originalSpreads[instanceID], num));
				}
				else
				{
					float num2 = originalSpreads[instanceID] * lastAppliedMultipliers[instanceID];
					Debug.Log((object)string.Format("[{0}] {1}({2}) Config Changed: {3} -> {4} (Multiplier: {5} -> {6})", "SolidAim", ((Object)component).name, instanceID, num2, num, lastAppliedMultipliers[instanceID], value));
				}
			}
			component.gunRandomSpread = num;
			lastAppliedMultipliers[instanceID] = value;
		}
		else
		{
			component.gunRandomSpread = originalSpreads[instanceID] * value;
		}
		HandleSolidAimState(__instance, component, val);
		if (SolidAim.AntiStuck.Value)
		{
			DetectThrashingAndRecover(__instance, component, val);
		}
	}

	private static void HandleSolidAimState(PhysGrabObject obj, ItemGun gun, PlayerAvatar player)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Invalid comparison between Unknown and I4
		bool value = SolidAim.AimStabilizationEnabled.Value;
		bool value2 = SolidAim.DroopWhenEmpty.Value;
		State val = (State)gunStateField.GetValue(gun);
		bool flag = (int)val == 1;
		float num = 1f;
		object value3 = gunBatteryField.GetValue(gun);
		if (value3 != null)
		{
			num = Traverse.Create(value3).Field("batteryLife").GetValue<float>();
			if (SolidAim.DebugMode.Value)
			{
				float time = Time.time;
				if (time - lastBatteryUpdateTime >= 1f)
				{
					lastBatteryUpdateTime = time;
					int instanceID = ((Object)gun).GetInstanceID();
					if (!lastBatteryLevels.ContainsKey(instanceID) || Mathf.Abs(lastBatteryLevels[instanceID] - num) > 0.01f)
					{
						lastBatteryLevels[instanceID] = num;
						Debug.Log((object)string.Format("[{0}] {1}({2}) Battery Updated: {3:F1}%", "SolidAim", ((Object)gun).name, instanceID, num));
					}
				}
			}
		}
		bool flag2 = num <= 0.1f;
		isResourceEmpty = flag2 || flag;
		bool flag3 = value;
		if (isResourceEmpty)
		{
			flag3 = !value2;
		}
		if (flag3)
		{
			ApplyAimStabilization(obj, gun, player);
		}
	}

	private static void ApplyAimStabilization(PhysGrabObject obj, ItemGun gun, PlayerAvatar player)
	{
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		bool flag = (bool)isCrouchingField.GetValue(player);
		gun.aimVerticalOffset = (flag ? (-1f) : (-3f));
		obj.OverrideMass(0.25f, 0.1f);
		obj.OverrideGrabStrength(2f, 0.1f);
		obj.OverrideTorqueStrength(5f, 0.1f);
		obj.OverrideDrag(2f, 0.1f);
		obj.rb.angularDrag = 29f;
		if (!isResourceEmpty)
		{
			gun.torqueMultiplier = 2f;
		}
		if ((Object)(object)Camera.main != (Object)null)
		{
			Quaternion rotation = ((Component)Camera.main).transform.rotation;
			obj.rb.rotation = Quaternion.Slerp(obj.rb.rotation, rotation, Time.fixedDeltaTime * 10f);
		}
	}

	private static void DetectThrashingAndRecover(PhysGrabObject obj, ItemGun gun, PlayerAvatar player)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: 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_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_0187: Unknown result type (might be due to invalid IL or missing references)
		Rigidbody rb = obj.rb;
		if ((Object)(object)rb == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)gun).GetInstanceID();
		Vector3 position = rb.position;
		if (!lastPos.ContainsKey(instanceID))
		{
			lastPos[instanceID] = position;
			thrashTimer[instanceID] = 0f;
			return;
		}
		float num = Vector3.Distance(position, lastPos[instanceID]);
		Vector3 angularVelocity = rb.angularVelocity;
		float magnitude = ((Vector3)(ref angularVelocity)).magnitude;
		Vector3 val = ((Component)obj).transform.position + ((Component)obj).transform.forward * 0.2f;
		bool flag = Physics.CheckSphere(val, 0.1f, layerMask, (QueryTriggerInteraction)1);
		if (num < 0.026f && magnitude > 1.3f && flag)
		{
			thrashTimer[instanceID] += Time.fixedDeltaTime * ((magnitude >= 15.99f) ? 3f : 1f);
		}
		else
		{
			thrashTimer[instanceID] = Mathf.Max(0f, thrashTimer[instanceID] - Time.fixedDeltaTime * 1.5f);
		}
		if (thrashTimer[instanceID] >= 0.11f)
		{
			ExecuteRecovery(obj, player);
			thrashTimer[instanceID] = 0f;
		}
		lastPos[instanceID] = position;
	}
}