using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon.Movement; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("AimAndCrouchToggles")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AimAndCrouchToggles")] [assembly: AssemblyTitle("AimAndCrouchToggles")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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; } } } [HarmonyPatch] public static class ToggleAimPatches { [HarmonyPatch(typeof(PlayerInput), "Initialize")] [HarmonyPostfix] public static void PlayerInputInitializePostfix() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) PlayerControls controls = PlayerInput.Controls; object aimAction; if (controls == null) { aimAction = null; } else { PlayerActions player = controls.Player; aimAction = ((PlayerActions)(ref player)).Aim; } AimAndCrouchTogglesPlugin.aimAction = (InputAction)aimAction; AimAndCrouchTogglesPlugin.ConfigureAimSubscription(); } [HarmonyPatch(typeof(Gun), "OnAimInputPerformed")] [HarmonyPrefix] public static bool SkipPrefix() { return !AimAndCrouchTogglesPlugin.toggleAim.Value; } [HarmonyPatch(typeof(Gun), "OnAimInputCancelled")] [HarmonyPrefix] public static bool SkipPrefixCancelled() { return !AimAndCrouchTogglesPlugin.toggleAim.Value; } [HarmonyPatch(typeof(Gun), "HandleAim")] [HarmonyPrefix] public static void HandleAimPrefix(Gun __instance) { if (AimAndCrouchTogglesPlugin.toggleAim.Value && __instance.IsAimEnabled) { AimAndCrouchTogglesPlugin.isAimInputHeldField.SetValue(__instance, AimAndCrouchTogglesPlugin.isAimToggled); if (AimAndCrouchTogglesPlugin.isAimToggled) { AimAndCrouchTogglesPlugin.lastPressedAimTimeField.SetValue(__instance, Time.time); } } } [HarmonyPatch(typeof(Gun), "Update")] [HarmonyPostfix] public static void UpdatePostfix(Gun __instance) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown if (AimAndCrouchTogglesPlugin.toggleAim.Value && __instance.IsAimEnabled) { bool flag = (bool)AimAndCrouchTogglesPlugin.isAimingGetter.Invoke(__instance, null); bool flag2 = (bool)AimAndCrouchTogglesPlugin.wantsToFireGetter.Invoke(__instance, null); float num = (float)AimAndCrouchTogglesPlugin.lastFireTimeGetter.Invoke(__instance, null); float num2 = (float)AimAndCrouchTogglesPlugin.lastPressedFireTimeField.GetValue(__instance); Player val = (Player)AimAndCrouchTogglesPlugin.playerField.GetValue(__instance); if ((Object)(object)val != (Object)null && !flag && !flag2 && Time.time - Mathf.Max(num, num2) > 0.5f) { val.ResumeSprint(); } } } [HarmonyPatch(typeof(Player), "Resurrect_ClientRpc")] [HarmonyPostfix] public static void ResetTogglePostfix() { AimAndCrouchTogglesPlugin.isAimToggled = false; } } [HarmonyPatch] public static class ToggleCrouchPatches { public static bool isToggleOn; [HarmonyPatch(typeof(Player), "Update")] [HarmonyPrefix] public static void Prefix(Player __instance) { //IL_0011: 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) if (!AimAndCrouchTogglesPlugin.toggleCrouch.Value) { return; } PlayerActions player = PlayerInput.Controls.Player; if (((PlayerActions)(ref player)).Slide.WasPressedThisFrame()) { PropertyInfo? property = typeof(Player).GetProperty("Crouching"); PropertyInfo property2 = typeof(Player).GetProperty("Sliding"); bool num = (bool)property.GetValue(__instance); bool flag = (bool)property2.GetValue(__instance); if (num || flag || isToggleOn) { isToggleOn = false; } else { isToggleOn = true; } } } } [HarmonyPatch] public static class EndCrouchPatches { [HarmonyPatch(typeof(Player), "EndCrouch")] [HarmonyPrefix] private static bool Prefix() { if (AimAndCrouchTogglesPlugin.toggleCrouch.Value) { return !ToggleCrouchPatches.isToggleOn; } return true; } } [HarmonyPatch] public static class EndSlidePatches { [HarmonyPatch(typeof(Player), "EndSlide")] [HarmonyPrefix] private static bool Prefix() { if (AimAndCrouchTogglesPlugin.toggleCrouch.Value) { return !ToggleCrouchPatches.isToggleOn; } return true; } } [BepInPlugin("sparroh.aimandcrouchtoggles", "AimAndCrouchToggles", "1.1.1")] [MycoMod(/*Could not decode attribute arguments.*/)] public class AimAndCrouchTogglesPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.aimandcrouchtoggles"; public const string PluginName = "AimAndCrouchToggles"; public const string PluginVersion = "1.1.1"; internal static ManualLogSource Logger; internal static ConfigEntry toggleAim; internal static ConfigEntry toggleCrouch; internal static bool isAimToggled; internal static InputAction aimAction; internal static FieldInfo isAimInputHeldField; internal static FieldInfo lastPressedAimTimeField; internal static FieldInfo lastPressedFireTimeField; internal static FieldInfo playerField; internal static MethodInfo isAimingGetter; internal static MethodInfo wantsToFireGetter; internal static MethodInfo lastFireTimeGetter; private FileSystemWatcher configWatcher; private volatile bool configReloadPending; private int lastConfigChangeTick; private const int ConfigReloadDebounceMs = 250; internal static AimAndCrouchTogglesPlugin Instance { get; set; } private void Awake() { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Instance = this; Logger = ((BaseUnityPlugin)this).Logger; toggleAim = ((BaseUnityPlugin)this).Config.Bind("General", "Toggle Aim", true, "If true, aim becomes a toggle (press to enter/exit) instead of hold."); toggleCrouch = ((BaseUnityPlugin)this).Config.Bind("General", "Toggle Crouch", true, "If true, enables toggle crouch functionality (hold crouch by pressing slide button)."); toggleAim.SettingChanged += OnToggleAimChanged; toggleCrouch.SettingChanged += OnToggleCrouchChanged; SetupConfigWatcher(); try { SetupAccessTools(); } catch (Exception ex) { Logger.LogError((object)("Error setting up access tools: " + ex.Message)); } try { Harmony val = new Harmony("sparroh.aimandcrouchtoggles"); val.PatchAll(typeof(ToggleAimPatches)); val.PatchAll(typeof(ToggleCrouchPatches)); val.PatchAll(typeof(EndCrouchPatches)); val.PatchAll(typeof(EndSlidePatches)); } catch (Exception ex2) { Logger.LogError((object)("Error applying patches: " + ex2.Message)); } Logger.LogInfo((object)"AimAndCrouchToggles loaded successfully."); } private void Update() { if (!configReloadPending || Environment.TickCount - lastConfigChangeTick < 250) { return; } configReloadPending = false; try { ((BaseUnityPlugin)this).Config.Reload(); Logger.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { Logger.LogError((object)("Failed to reload config: " + ex.Message)); } } private void SetupConfigWatcher() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; string directoryName = Path.GetDirectoryName(configFilePath); string fileName = Path.GetFileName(configFilePath); if (string.IsNullOrEmpty(directoryName) || string.IsNullOrEmpty(fileName)) { Logger.LogWarning((object)"Could not set up config hot-reload: invalid config path."); return; } configWatcher = new FileSystemWatcher(directoryName, fileName) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), EnableRaisingEvents = true }; configWatcher.Changed += OnConfigFileChanged; configWatcher.Created += OnConfigFileChanged; configWatcher.Renamed += OnConfigFileRenamed; Logger.LogInfo((object)("Watching config for hot-reload: " + configFilePath)); } catch (Exception ex) { Logger.LogError((object)("Failed to set up config watcher: " + ex.Message)); } } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { lastConfigChangeTick = Environment.TickCount; configReloadPending = true; } private void OnConfigFileRenamed(object sender, RenamedEventArgs e) { string fileName = Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath); if (string.Equals(e.Name, fileName, StringComparison.OrdinalIgnoreCase) || string.Equals(e.OldName, fileName, StringComparison.OrdinalIgnoreCase)) { lastConfigChangeTick = Environment.TickCount; configReloadPending = true; } } private void SetupAccessTools() { isAimInputHeldField = AccessTools.Field(typeof(Gun), "isAimInputHeld"); lastPressedAimTimeField = AccessTools.Field(typeof(Gun), "lastPressedAimTime"); lastPressedFireTimeField = AccessTools.Field(typeof(Gun), "lastPressedFireTime"); playerField = AccessTools.Field(typeof(Gun), "player"); isAimingGetter = AccessTools.PropertyGetter(typeof(Gun), "IsAiming"); wantsToFireGetter = AccessTools.PropertyGetter(typeof(Gun), "WantsToFire"); lastFireTimeGetter = AccessTools.PropertyGetter(typeof(Gun), "LastFireTime"); } private void OnToggleAimChanged(object sender, EventArgs e) { ConfigureAimSubscription(); } private void OnToggleCrouchChanged(object sender, EventArgs e) { if (!toggleCrouch.Value) { ToggleCrouchPatches.isToggleOn = false; } } internal static void ConfigureAimSubscription() { if (aimAction != null) { aimAction.started -= OnAimStarted; if (toggleAim.Value) { aimAction.started += OnAimStarted; } else { isAimToggled = false; } } } internal static void OnAimStarted(CallbackContext context) { if (toggleAim.Value) { isAimToggled = !isAimToggled; } } private void OnDestroy() { if (configWatcher != null) { configWatcher.EnableRaisingEvents = false; configWatcher.Changed -= OnConfigFileChanged; configWatcher.Created -= OnConfigFileChanged; configWatcher.Renamed -= OnConfigFileRenamed; configWatcher.Dispose(); configWatcher = null; } if (aimAction != null) { aimAction.started -= OnAimStarted; } } } namespace AimAndCrouchToggles { public static class MyPluginInfo { public const string PLUGIN_GUID = "AimAndCrouchToggles"; public const string PLUGIN_NAME = "AimAndCrouchToggles"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }