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 _enabledCfg; private static ConfigEntry _strengthCfg; private static ConfigEntry _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("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("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(0f, 100f), Array.Empty())); _distanceCfg = ((BaseUnityPlugin)this).Config.Bind("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(10f, 150f), Array.Empty())); 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(); 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); } } } }