From 6defa601d5392dddf90cf110d29fb0fb41e8e8e8 Mon Sep 17 00:00:00 2001 From: Justin Oros Date: Sun, 20 Sep 2026 23:24:34 -0700 Subject: [PATCH] Auto reload presses the reload key so the game plays its reload animation --- FullAuto.cs | 109 +++++++++++++++++++++++++++++++++----------------- README.md | 8 ++-- manifest.json | 2 +- 3 files changed, 77 insertions(+), 42 deletions(-) diff --git a/FullAuto.cs b/FullAuto.cs index 3a685d5..b0babcd 100644 --- a/FullAuto.cs +++ b/FullAuto.cs @@ -39,6 +39,7 @@ public class FullAuto : SonsMod internal static bool FastReload; internal static bool AutoReload; internal static KeyCode FlashlightKey = KeyCode.F; + internal static string ReloadKey = "r"; internal static bool Verbose; private static string _configPath; @@ -60,6 +61,7 @@ public class FullAuto : SonsMod private void OnUpdate() { CheckFireInputPatch.UpdateTrigger(); + CheckFireInputPatch.UpdateReloadKey(); if (!CheckFireInputPatch.HoldingGun) CheckFireInputPatch.RestoreReloadSpeed(); @@ -205,6 +207,8 @@ public class FullAuto : SonsMod FastReload = fast; else if (key == "autoreload" && bool.TryParse(val, out var auto)) AutoReload = auto; + else if (key == "reloadkey" && val.Length > 0) + ReloadKey = val.ToLowerInvariant(); else if (key == "flashlightkey" && Enum.TryParse(val, true, out var flashKey)) FlashlightKey = flashKey; else if (key.StartsWith("mode.") && Enum.TryParse(val, true, out var gunMode)) @@ -226,6 +230,7 @@ public class FullAuto : SonsMod sb.Append($"fastreload={FastReload.ToString().ToLowerInvariant()}\n"); sb.Append($"autoreload={AutoReload.ToString().ToLowerInvariant()}\n"); sb.Append($"flashlightkey={FlashlightKey}\n"); + sb.Append($"reloadkey={ReloadKey}\n"); foreach (var gun in CheckFireInputPatch.GunKeys) { var mode = Modes.TryGetValue(gun, out var m) ? m : FireMode.Auto; @@ -247,8 +252,6 @@ internal static class CheckFireInputPatch private const int BurstSize = 3; private const float ReleaseTime = 0.15f; private const float AutoReloadDelay = 0.2f; - private const float AutoReloadNextDelay = 0.05f; - private const float AutoReloadRoundTime = 0.9f; private static readonly Dictionary Guns = new() { @@ -285,10 +288,11 @@ internal static class CheckFireInputPatch private static readonly List Lights = new(); private static float _emptySince = -1f; private static float _nextReloadTry; - private static bool _autoReloading; - private static IntPtr _autoReloadGun = IntPtr.Zero; - private static float _lastReloadCall = -10f; - private static bool _sawReloading; + private static UnityEngine.InputSystem.Controls.KeyControl _reloadControl; + private static string _reloadControlKey; + private static UnityEngine.InputSystem.Controls.KeyControl _pressedKey; + private static int _releaseFrame = -1; + private static bool _keySimFailed; private static bool _loggedHook; internal static bool HoldingGun => _lastGunTime >= 0f && Time.time - _lastGunTime < 0.25f; @@ -356,13 +360,11 @@ internal static class CheckFireInputPatch if (!FullAuto.AutoReload || !InGame) { _emptySince = -1f; - _autoReloading = false; return; } if (controller._isReloading || controller.IsReloading() || controller.IsReloadQueued()) { - _sawReloading = true; _emptySince = -1f; return; } @@ -372,20 +374,7 @@ internal static class CheckFireInputPatch return; var ammo = weapon.GetAmmo(); - if (ammo == null) - return; - - if (_autoReloading && (_autoReloadGun != controller.Pointer || ammo.IsFull())) - _autoReloading = false; - - if (FirePressed()) - { - _autoReloading = false; - _emptySince = -1f; - return; - } - - if (!ammo.IsEmpty() && !_autoReloading) + if (ammo == null || !ammo.IsEmpty() || FirePressed()) { _emptySince = -1f; return; @@ -398,30 +387,76 @@ internal static class CheckFireInputPatch return; } - var wait = _autoReloading ? AutoReloadNextDelay : AutoReloadDelay; - if (now - _emptySince < wait || now < _nextReloadTry) + if (now - _emptySince < AutoReloadDelay || now < _nextReloadTry) return; - var roundTime = FullAuto.FastReload ? AutoReloadRoundTime / FullAuto.ReloadMultiplier : AutoReloadRoundTime; - if (_autoReloading && !_sawReloading && now - _lastReloadCall < roundTime) - return; - - _nextReloadTry = now + 0.3f; + _nextReloadTry = now + 2f; if (!controller.CanReload()) + return; + + if (PressReloadKey()) { - _autoReloading = false; + if (FullAuto.Verbose) + RLog.Msg($"FullAuto auto reload pressed {FullAuto.ReloadKey} on {controller.GetIl2CppType().Name}"); return; } - controller.Reload(); - _autoReloading = true; - _autoReloadGun = controller.Pointer; - _lastReloadCall = now; - _sawReloading = false; + controller._reloadQueued = true; if (FullAuto.Verbose) - RLog.Msg($"FullAuto auto reload {controller.GetIl2CppType().Name}, ammo {ammo.GetRemainingAmmo()}/{ammo.GetCapacity()}"); + RLog.Msg($"FullAuto auto reload queued on {controller.GetIl2CppType().Name}"); + } + + private static bool PressReloadKey() + { + if (_keySimFailed || _pressedKey != null) + return false; + + try + { + if (_reloadControl == null || _reloadControlKey != FullAuto.ReloadKey) + { + _reloadControlKey = FullAuto.ReloadKey; + var control = UnityEngine.InputSystem.InputSystem.FindControl($"/{FullAuto.ReloadKey}"); + _reloadControl = control?.TryCast(); + } + + if (_reloadControl == null) + { + _keySimFailed = true; + RLog.Warning($"FullAuto could not find reload key {FullAuto.ReloadKey}"); + return false; + } + + UnityEngine.InputSystem.InputControlExtensions.QueueValueChange(_reloadControl, 1f, -1d); + _pressedKey = _reloadControl; + _releaseFrame = Time.frameCount + 3; + return true; + } + catch (Exception e) + { + _keySimFailed = true; + RLog.Warning($"FullAuto could not press reload key: {e.Message}"); + return false; + } + } + + internal static void UpdateReloadKey() + { + if (_pressedKey == null || Time.frameCount < _releaseFrame) + return; + + try + { + UnityEngine.InputSystem.InputControlExtensions.QueueValueChange(_pressedKey, 0f, -1d); + } + catch (Exception e) + { + RLog.Warning($"FullAuto could not release reload key: {e.Message}"); + } + + _pressedKey = null; } internal static void CancelBurst() @@ -771,4 +806,4 @@ internal static class CheckFireInputPatch RLog.Msg($"FullAuto {name}: {(allowed ? "full-auto" : "ignored")}"); return allowed; } -} +} \ No newline at end of file diff --git a/README.md b/README.md index b5382d7..6d4511d 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ Press F1 to open the console, then use these commands: | `fullauto off` | Disable until the game restarts | | `fullauto rpm 1200` | Set the fire rate, 60 to 3000 rounds per minute | | `fullauto fastreload on` | Reload guns twice as fast, `off` to turn it back off | -| `fullauto autoreload on` | Reload automatically when the gun is empty, `off` to turn it back off | +| `fullauto autoreload on` | Reload automatically when the gun is empty, `off` to turn it back off. It presses your reload key for you, so if you changed it from R in the game settings, set `reloadkey=` in `FullAuto.txt` to match | | `fullauto debug` | Log every shot to `_RedLoader\Latest.log` | The default is 900 rpm. The rpm also sets how fast burst shots fire. -The rpm, fast reload, auto reload, flashlight key and each gun's fire mode are -saved to +The rpm, fast reload, auto reload, flashlight key, reload key and each gun's fire +mode are saved to `UserData\FullAuto.txt` in your game folder. ## Supported weapons @@ -109,4 +109,4 @@ the game is not found automatically. ## Troubleshooting Check `_RedLoader\Latest.log` in your game folder. FullAuto logs a line when it loads and a line for each weapon showing whether it is full-auto or -ignored. +ignored. \ No newline at end of file diff --git a/manifest.json b/manifest.json index e640365..dd1ab06 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "id": "FullAuto", "name": "FullAuto", "author": "JustinOros", - "version": "1.5.3", + "version": "1.5.4", "description": "Full-auto, semi-auto and 3-round burst for guns, with fast reload and a flashlight toggle", "gameVersion": "1.0.0", "platform": "Client",