Decompiled source of AimAssist v1.0.1

BepInEx/plugins/AimAssist.dll

Decompiled a week ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.Movement;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Coruscnium")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Controller aim assist for Mycopunk: COD-Zombies-style tracking magnetism plus a lighter slowdown-only mode.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1.0")]
[assembly: AssemblyProduct("AimAssist")]
[assembly: AssemblyTitle("AimAssist")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AimAssist
{
	[BepInPlugin("coruscnium.aimassist", "AimAssist", "1.0.1.0")]
	[BepInProcess("Mycopunk.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private static ConfigEntry<bool> _enabledCfg;

		private static ConfigEntry<float> _strengthCfg;

		private static ConfigEntry<float> _distanceCfg;

		private static bool _enabled = true;

		private static float _strength = 100f;

		private static float _distance = 60f;

		private const float SlowdownStrengthFull = 70f;

		private const float TrackStrengthFull = 50f;

		private const float SnapStrengthFull = 40f;

		private const float SlowdownCone = 7f;

		private const float SnapCone = 8f;

		private const float MaxTrackGain = 10f;

		private const float MaxSnapGain = 30f;

		private const float SnapDuration = 0.18f;

		private const float TrackReleaseDuration = 0.35f;

		private const float FullStrengthRangeFraction = 0.5f;

		private const float SlowdownEngageRate = 25f;

		private const float SlowdownReleaseRate = 7f;

		private const float MaxAssistDegPerSec = 60f;

		private const float AssistFloorDeg = 2f;

		private const float AssistDeadzoneDeg = 0.5f;

		private static FieldInfo _playerMovementField;

		private static bool _targetMaskResolved;

		private static int _targetMask = -5;

		private static bool _prevAimPressed;

		private static ISelectable _snapTarget;

		private static float _snapElapsed;

		private static float _slowFactor = 1f;

		private static int _slowFrame = -1;

		private static ISelectable _trackTarget;

		private static float _trackEngage;

		private static Vector3 _trackLastPoint;

		private static readonly Collider[] _overlapBuffer = (Collider[])(object)new Collider[64];

		private static FileSystemWatcher _configWatcher;

		private static volatile bool _pendingConfigReload;

		private void Awake()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"AimAssist loading...");
			_enabledCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master on/off for controller aim assist (gamepad only). When on, it combines look-speed slowdown near a target with COD-Zombies-style magnetism (tracking once your reticle is on a target, plus an eased snap when you press Aim).");
			_strengthCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Strength", 100f, new ConfigDescription("Overall aim-assist strength, as a percent of the default feel (100 = default, lower = gentler, 0 = effectively off). Cones and the slowdown/tracking/snap balance are fixed at sensible defaults.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			_distanceCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Distance", 60f, new ConfigDescription("Range (metres) the assist reaches. Targets beyond this get no help; the assist is full-strength up close and tapers to nothing at this distance. Higher = pushes the taper further out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 150f), Array.Empty<object>()));
			CacheConfig();
			((BaseUnityPlugin)this).Config.Save();
			_enabledCfg.SettingChanged += delegate
			{
				CacheConfig();
			};
			_strengthCfg.SettingChanged += delegate
			{
				CacheConfig();
			};
			_distanceCfg.SettingChanged += delegate
			{
				CacheConfig();
			};
			Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			try
			{
				_configWatcher = new FileSystemWatcher(Paths.ConfigPath, "coruscnium.aimassist.cfg")
				{
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
					EnableRaisingEvents = true
				};
				_configWatcher.Changed += OnConfigFileChanged;
				_configWatcher.Created += OnConfigFileChanged;
				_configWatcher.Renamed += OnConfigFileChanged;
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Could not start config file watcher: " + ex.Message));
			}
			Logger.LogInfo((object)$"AimAssist loaded. Enabled: {_enabled}");
		}

		private static void CacheConfig()
		{
			_enabled = _enabledCfg.Value;
			_strength = _strengthCfg.Value;
			_distance = _distanceCfg.Value;
		}

		private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			_pendingConfigReload = true;
		}

		private void Update()
		{
			if (_pendingConfigReload)
			{
				_pendingConfigReload = false;
				try
				{
					((BaseUnityPlugin)this).Config.Reload();
				}
				catch (Exception ex)
				{
					Logger.LogError((object)("Config reload failed: " + ex.Message));
				}
				CacheConfig();
			}
		}

		private void OnDestroy()
		{
			if (_configWatcher != null)
			{
				_configWatcher.EnableRaisingEvents = false;
				_configWatcher.Dispose();
				_configWatcher = null;
			}
		}

		private static bool GamepadActiveAndPlaying()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)PlayerInput.Device == 0)
			{
				return false;
			}
			if (!PlayerInput.IsPlayerEnabled)
			{
				return false;
			}
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				return localPlayer.IsAlive;
			}
			return false;
		}

		private static int TargetMask()
		{
			//IL_0051: 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)
			if (_targetMaskResolved)
			{
				return _targetMask;
			}
			_targetMaskResolved = true;
			try
			{
				Highlighter instance = Highlighter.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					FieldInfo fieldInfo = AccessTools.Field(typeof(Highlighter), "targetLayerMask");
					if (fieldInfo != null && fieldInfo.GetValue(instance) is LayerMask val)
					{
						_targetMask = ((LayerMask)(ref val)).value;
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("targetLayerMask reflection failed, using default: " + ex.Message));
			}
			return _targetMask;
		}

		private static bool TryGetAimPoint(ISelectable sel, out Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0069: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			point = default(Vector3);
			if (sel == null || (Object)(object)sel.transform == (Object)null)
			{
				return false;
			}
			Collider componentInChildren = ((Component)sel.transform).GetComponentInChildren<Collider>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Bounds bounds = componentInChildren.bounds;
				point = ((Bounds)(ref bounds)).center;
				return true;
			}
			IFollowable val = (IFollowable)(object)((sel is IFollowable) ? sel : null);
			point = ((val != null) ? sel.transform.TransformPoint(val.HealthbarPosition) : sel.transform.position);
			return true;
		}

		private static bool IsLiveTarget(ISelectable sel)
		{
			if (sel != null)
			{
				ITarget val = (ITarget)(object)((sel is ITarget) ? sel : null);
				if (val != null && val.IsAlive)
				{
					return !(sel is Player);
				}
			}
			return false;
		}

		private static float DistanceFalloff(float dist)
		{
			if (dist >= _distance)
			{
				return 0f;
			}
			float num = _distance * 0.5f;
			if (dist <= num)
			{
				return 1f;
			}
			float num2 = (dist - num) / (_distance - num);
			return 1f - Mathf.SmoothStep(0f, 1f, num2);
		}

		private static float PrecisionGate(float errorAngle)
		{
			if (errorAngle <= 0.5f)
			{
				return 0f;
			}
			if (errorAngle >= 2f)
			{
				return 1f;
			}
			return Mathf.SmoothStep(0f, 1f, (errorAngle - 0.5f) / 1.5f);
		}

		private static bool TryFindTargetInCone(Vector3 camPos, Vector3 camFwd, float coneDeg, float range, out ISelectable best, out Vector3 bestPoint)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			best = null;
			bestPoint = default(Vector3);
			int num = TargetMask();
			int num2 = Physics.OverlapSphereNonAlloc(camPos, range, _overlapBuffer, num, (QueryTriggerInteraction)2);
			float num3 = coneDeg;
			RaycastHit val3 = default(RaycastHit);
			for (int i = 0; i < num2; i++)
			{
				Collider val = _overlapBuffer[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ISelectable selectable = IDamageSource.GetSelectable((Component)(object)val);
				if (!IsLiveTarget(selectable) || !TryGetAimPoint(selectable, out var point))
				{
					continue;
				}
				Vector3 val2 = point - camPos;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (!(magnitude < 0.01f) && !(magnitude > range))
				{
					float num4 = Vector3.Angle(camFwd, val2);
					if (!(num4 >= num3) && (!Physics.Linecast(camPos, point, ref val3, -5, (QueryTriggerInteraction)1) || IDamageSource.GetSelectable((Component)(object)((RaycastHit)(ref val3)).collider) == selectable || !(((RaycastHit)(ref val3)).distance < magnitude - 0.5f)))
					{
						num3 = num4;
						best = selectable;
						bestPoint = point;
					}
				}
			}
			return best != null;
		}

		private static void AimError(Vector3 camPos, Vector3 camFwd, Vector3 target, out float yawErr, out float pitchDeltaXLook, out float errorAngle)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			yawErr = 0f;
			pitchDeltaXLook = 0f;
			errorAngle = 0f;
			Vector3 val = target - camPos;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (!(magnitude < 0.0001f))
			{
				val /= magnitude;
				errorAngle = Vector3.Angle(camFwd, val);
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(camFwd.x, 0f, camFwd.z);
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor(val.x, 0f, val.z);
				if (((Vector3)(ref val2)).sqrMagnitude > 1E-06f && ((Vector3)(ref val3)).sqrMagnitude > 1E-06f)
				{
					yawErr = Vector3.SignedAngle(val2, val3, Vector3.up);
				}
				float num = Mathf.Asin(Mathf.Clamp(camFwd.y, -1f, 1f)) * 57.29578f;
				float num2 = Mathf.Asin(Mathf.Clamp(val.y, -1f, 1f)) * 57.29578f;
				pitchDeltaXLook = num - num2;
			}
		}

		private static Transform PlayerMovementTransform(PlayerLook look)
		{
			if (_playerMovementField == null)
			{
				_playerMovementField = AccessTools.Field(typeof(PlayerLook), "playerMovement");
			}
			object? obj = _playerMovementField?.GetValue(look);
			object? obj2 = ((obj is Component) ? obj : null);
			if (obj2 == null)
			{
				return null;
			}
			return ((Component)obj2).transform;
		}

		[HarmonyPatch(typeof(PlayerLook), "SlowGamepadLookSpeed")]
		[HarmonyPrefix]
		private static bool SlowGamepadLookSpeed_Prefix(ref bool __result)
		{
			if (_enabled && _strength > 0f)
			{
				__result = false;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerLook), "GetMouseDelta")]
		[HarmonyPostfix]
		private static void GetMouseDelta_Postfix(PlayerLook __instance, ref Vector2 __result)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled || _strength <= 0f || !GamepadActiveAndPlaying())
			{
				_slowFactor = 1f;
				return;
			}
			Camera camera = __instance.Camera;
			if ((Object)(object)camera == (Object)null)
			{
				return;
			}
			if (Time.frameCount != _slowFrame)
			{
				_slowFrame = Time.frameCount;
				Transform transform = ((Component)camera).transform;
				float num = 1f;
				if (TryFindTargetInCone(transform.position, transform.forward, 7f, _distance, out var _, out var bestPoint))
				{
					float num2 = Vector3.Angle(transform.forward, bestPoint - transform.position);
					float num3 = Mathf.Clamp01(1f - num2 / 7f);
					float num4 = 0.7f * (_strength / 100f);
					num = 1f - num4 * num3;
				}
				float num5 = Mathf.Min(Time.unscaledDeltaTime, 0.1f);
				float num6 = ((num < _slowFactor) ? 25f : 7f);
				_slowFactor += (num - _slowFactor) * (1f - Mathf.Exp((0f - num6) * num5));
			}
			__result *= _slowFactor;
		}

		[HarmonyPatch(typeof(PlayerLook), "HandleCameraControl")]
		[HarmonyPostfix]
		private static void HandleCameraControl_Postfix(PlayerLook __instance)
		{
			//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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled || !GamepadActiveAndPlaying())
			{
				_prevAimPressed = false;
				_snapTarget = null;
				_trackTarget = null;
				_trackEngage = 0f;
				return;
			}
			Camera camera = __instance.Camera;
			if ((Object)(object)camera == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)camera).transform;
			Vector3 position = transform.position;
			Vector3 forward = transform.forward;
			float num = Mathf.Min(Time.deltaTime, 0.1f);
			float num2 = _strength / 100f;
			PlayerActions player = PlayerInput.Controls.Player;
			bool flag = ((PlayerActions)(ref player)).Aim.IsPressed();
			if (num2 > 0f && flag && !_prevAimPressed && TryFindTargetInCone(position, forward, 8f, _distance, out var best, out var _))
			{
				_snapTarget = best;
				_snapElapsed = 0f;
			}
			_prevAimPressed = flag;
			float num3 = 0f;
			float num4 = 0f;
			bool flag2 = false;
			if (_snapTarget != null)
			{
				if (IsLiveTarget(_snapTarget) && TryGetAimPoint(_snapTarget, out var point))
				{
					_snapElapsed += num;
					float num5 = Mathf.Clamp01(_snapElapsed / 0.18f);
					float num6 = Mathf.SmoothStep(0f, 1f, num5);
					float num7 = DistanceFalloff(Vector3.Distance(position, point));
					float num8 = 12f * num2 * num7 * num6;
					float num9 = 1f - Mathf.Exp((0f - num8) * num);
					AimError(position, forward, point, out var yawErr, out var pitchDeltaXLook, out var errorAngle);
					float num10 = num9 * PrecisionGate(errorAngle);
					num3 += yawErr * num10;
					num4 += pitchDeltaXLook * num10;
					flag2 = true;
					if (num5 >= 1f)
					{
						_snapTarget = null;
					}
				}
				else
				{
					_snapTarget = null;
				}
			}
			if (!flag2 && num2 > 0f)
			{
				ISelectable val = (((Object)(object)Highlighter.Instance != (Object)null) ? Highlighter.Instance.SelectedTarget : null);
				if (IsLiveTarget(val))
				{
					_trackTarget = val;
					_trackEngage = 1f;
				}
				else if (_trackTarget != null)
				{
					_trackEngage -= num / 0.35f;
					if (_trackEngage <= 0f)
					{
						_trackTarget = null;
						_trackEngage = 0f;
					}
				}
				if (_trackTarget != null && _trackEngage > 0f)
				{
					if (IsLiveTarget(_trackTarget) && TryGetAimPoint(_trackTarget, out var point2))
					{
						_trackLastPoint = point2;
					}
					float num11 = DistanceFalloff(Vector3.Distance(position, _trackLastPoint));
					if (num11 > 0f)
					{
						float num12 = 5f * num2 * num11 * _trackEngage;
						float num13 = 1f - Mathf.Exp((0f - num12) * num);
						AimError(position, forward, _trackLastPoint, out var yawErr2, out var pitchDeltaXLook2, out var errorAngle2);
						float num14 = num13 * PrecisionGate(errorAngle2);
						num3 += yawErr2 * num14;
						num4 += pitchDeltaXLook2 * num14;
					}
				}
			}
			if (num3 == 0f && num4 == 0f)
			{
				return;
			}
			float num15 = 60f * num;
			float num16 = Mathf.Sqrt(num3 * num3 + num4 * num4);
			if (num16 > num15 && num16 > 1E-06f)
			{
				float num17 = num15 / num16;
				num3 *= num17;
				num4 *= num17;
			}
			if (num3 != 0f)
			{
				Transform val2 = PlayerMovementTransform(__instance);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.localRotation *= Quaternion.Euler(0f, num3, 0f);
				}
			}
			if (num4 != 0f)
			{
				__instance.XLookRotation = Mathf.Clamp(__instance.XLookRotation + num4, -89f, 89f);
			}
		}
	}
}